---
project
  data
version
  0.0.0
links
  ["foundation.tofg.js"]
unit
  struct
info
  `data` is a project comprising common and/or important data structures.
---
---








---
// ////////////////////////////////////////////////////////////////////////////////////////////////
---
unit
  doc
header
  **Data Structures**
---
---
unit
  struct
name
  Data
---
// ////////////////////////////////////////////////////////////////////////////////////////////////
---







---
---
unit
  doc
name
  Data
header
  **Typed Versions of Native ECMAScript Data Structures**
---
---












---
// Data.Bit
---
unit
  doc
name
  Data
header
  Bit value operations on (small/safe) integers
---
unit
  struct
name
  Data.Bit
info
  For the [bitwise operations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators).
---
unit
  function
name
  Data.Bit.and
type
  Type.lambda ([INT, INT, INT])
value
  function (i1) {
    return function (i2) {
      return (i1 & i2);
    }
  }
info
  ....
---
unit
  function
name
  Data.Bit.or
type
  Type.lambda ([INT, INT, INT])
value
  function (i1) {
    return function (i2) {
      return (i1 | i2);
    }
  }
info
  ....
---
unit
  function
name
  Data.Bit.xor
type
  Type.lambda ([INT, INT, INT])
value
  function (i1) {
    return function (i2) {
      return (i1 ^ i2);
    }
  }
info
  `Data.Bit.xor(x)(y)` is the wrapper function for the native ECMAScript XOR operation `x ^ y`.

  [XOR](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR)
  stands for _Exclusive OR__, i.e. `x` or `y`, but not both.
---
unit
  function
name
  Data.Bit.left
type
  Type.lambda ([INT, INT, INT])
value
  function (i1) {
    return function (i2) {
      return (i1 << i2);
    }
  }
info
  [Left shift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Left_shift)
---
unit
  function
name
  Data.Bit.right
type
  Type.lambda ([INT, INT, INT])
value
  function (i1) {
    return function (i2) {
      return (i1 >> i2);
    }
  }
info
  [Sign-propagating right shift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Right_shift)
---
unit
  function
name
  Data.Bit.right0
type
  Type.lambda ([INT, INT, INT])
value
  function (i1) {
    return function (i2) {
      return (i1 >>> i2);
    }
  }
info
  [Zero-fill right shift](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Unsigned_right_shift)
---

---
// end Data.Bit
---








---
unit
  doc
name
  Data
header
  Localizations
---
unit
  struct
name
  Data.Locale
---
unit
  function
name
  Data.Locale.comparison
type
  Type.lambda ([STRING, STRING, STRING, Type.finite ([-1,0,1])])
value
  function () {
    return "..................Data.Locale.comparison....................................";
  }
info
  .....

  See [`String::localeCompare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Checking_for_support_for_locales_and_options_arguments)
---
unit
  function
name
  Data.Locale.toUpperCase
type
  Type.lambda ([STRING, STRING])
value
  function (s) {
    return s.toLocaleUpperCase();
  }
info
  `Data.Locale.toUpperCase(s)` returns the `s`, converted to upper case, according to any locale-specific case mappings.
  In most cases, the result is the same as `Str.toUpperCase(s)`.
  See the native [`String::toLocaleUpperCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLocaleUpperCase).
---
unit
  function
name
  Data.Locale.toLowerCase
type
  Type.lambda ([STRING, STRING])
value
  function (s) {
    return s.toLocaleLowerCase();
  }
info
  `Data.Locale.toLowerCase(s)` returns the `s`, converted to lower case, according to any locale-specific case mappings.
  In most cases, the result is the same as `Str.toLowerCase(s)`.
  See the native [`String::toLocaleLowerCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLocaleLowerCase).
---
---
// Dat.Locale
---








---
// Data.DateTime
---
unit
  doc
name
  Data
header
  Date and Time
---
unit
  type
name
  Data.DATETIME
value
  Type.fromRecord ({
    complain:
      function (x) {
        if (x instanceof Date) { return ''; }
        else { return "Not a date object." }
      },
    chi:
      function (x) { return (x instanceof Date); },
    name:
      'Data.DATETIME',
    cardinality:
      function () { return null; }
  })
---
unit
  struct
name
  Data.DateTime
info
  ....

  Given UNIX time, then the range of dates is approximately 285,616 years from either side of midnight, January 1, 1970.
  Negative numbers indicate dates prior to 1970.

  ....
comment
  A structure comprising the data structures and functions to deal with date and time.

  # Native ECMAScript `Date` objects and its three distinct representation formats

  ECMAScript has a native `Date` class for the representation of date and time.
  In our typology, these objects are the members of the `$inst('Date')` type.
  Such a `Date` object has no native representation in ECMAScript, but there are a couple of built-in conversions into three distinct formats:

  * A __POSIX time stamp__ (also called [Unix time](https://en.wikipedia.org/wiki/Unix_epoch) or Epoch time) is the representation of as the number of seconds that have elapsed since 00:00:00 UTC, 1 January 1970, not counting leap seconds. For example, `1401485902901` is the current time stamp.

  * __date-time strings__, such as

      * the __ISO notation__ (according to the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard. For example, the current moment is given as `"2014-05-30T21:38:22.901Z"`.

      * the __UTC__ (or [Greenwich Mean Time](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) standard, where the same moment is given as `"Fri, 30 May 2014 21:38:22 GMT"`

      * various __local time notations__, depending on the local settings, e.g. `"Fri May 30 2014 23:38:22 GMT+0200 (CEST)"`

  * A __date-time record__, for example, `{year: 2014, month: 4, day: 30, hour: 23, minute: 38, second: 22, millisecond: 0}` (where `month:4` stands for "May", because the counting is zero-based and January is `0`.)

  # The types

  According to the four different data types for date and time, we have four different types, the last three are defined explicitly:

  * `$inst('Date')` the instance objects of the `Date` class, native objects of ECMASCript
  * `DATETIMENumber` which is just a synonym for `INT`,
  * `DATETIMEString`, which is a synonym for `STRING`, and
  * `DATETIME_RECORD`, which is type of all the models of the signature

            { year        : INT,
              month       : $range ([0, 11]), // `0` is January, `1` is February, ..., `11` is December
              day         : $range ([1, 31]), // for day of the month
              hour        : $range ([0, 23]),
              minute      : $range ([0, 59]),
              second      : $range ([0, 59]),
              millisecond : $range ([0, 999]) }

        and the optional properties

            { week        : $range ([0, 53]),
              day         : $range ([0, 6])    }

---
unit
  local function
name
  Data.DateTime.getWeek
type
  Type.lambda ([DATETIME, Type.range ([1,53])])
info
  `Data.DateTime.getWeek(d)` gets the week number of the `Date` object `d`.
comment
  The implementation is taken from [weeknumber.net](http://weeknumber.net/how-to/javascript)
value
  function (d) {
    var date = new Date (d.getTime ());
    date.setHours (0, 0, 0, 0);
    // Thursday in current week decides the year.
    date.setDate (date.getDate () + 3 - (date.getDay () + 6) % 7);
    // January 4 is always in week 1.
    var week1 = new Date (date.getFullYear (), 0, 4);
    // Adjust to Thursday in week 1 and count number of weeks from date to week1.
    return 1 + Math.round (((date.getTime () - week1.getTime ()) / 86400000 - 3 + (week1.getDay () + 6) % 7) / 7);
  }
---
unit
  value
name
  Data.DateTime.now
type
  Type.function ([NULL, DATETIME])
value
  function () { return new Date(); }
info
  A call of `Data.DateTime.now()` returns a `DATETIME` object with the current date and time.

  For example,

      > var dt = Data.DateTime.now()
      > Data.DateTime.toString (dt)
      Mon Jun 30 2014 18:02:06 GMT+0200 (CEST)

comment
  ECMAScript has two versions to ask for the current Date/Time: `new Date()` returns a `Date` object and `Date.now()` returns the Posix time stamp (integer).
---
unit
  value
name
  Data.DateTime.localeOffset
type
  Type.function ([NULL, INT])
value
  function () {
    var d = new Date ();
    return d.getTimezoneOffset();
  }
info
  `Data.DateTime.localeOffset()` returns the difference between UTC and local time, given in minutes.
   The number is positive, if the current local time is behind UTC (e.g. Pacific Daylight Time), and negative, if the local time is ahead of UTC (e.g. Japan). For example, if the local timezone is UTC+10 (Australian Eastern Standard Time), the offset is -600.
---
unit
  function
name
  Data.DateTime.fromInt
type
  Type.lambda ([INT, DATETIME])
value
  function (i) { return new Date (i); }
info
  `Data.DateTime.fromInt(i)` returns the `DATETIME` object that has the [UNIX time](https://en.wikipedia.org/wiki/Unix_time) represented by the integer `i`, where `i` is the number of milliseconds that have elapsed since `00:00:00` [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time), Thurday, 1 January 1970, not counting leap seconds.
---
unit
  function
name
  Data.DateTime.toInt
type
  Type.lambda ([DATETIME, INT])
value
  function (d) { return d.getTime(); }
---
unit
  function
name
  Data.DateTime.fromString
type
  Type.lambda ([STRING, DATETIME])
value
  function (s) {
    var n = Date.parse (s);  // integer for the internal millisecond representation of `s`
    var d = new Date (n);
    if (isNaN (n)) {
      throw Error ("`Data.DateTime.fromString(s)` error, the argument is not a string representation of a date/time: `" + Any.literal(s) + "`.");
    } else {
      if (d === undefined) {
        throw Error ("`Data.DateTime.fromString(s)` error, the string argument cannot be converted `" + Any.literal(s) + "`.");
      } else {
        return d;
      }
    }
  }
info
  `Data.DateTime.fromString(s)` parses `s` and converts it into a `DATETIME` object.
  Accepted `s` are in [ISO 8601](http://www.w3.org/TR/NOTE-datetime) or [RFC2822](http://tools.ietf.org/html/rfc2822#page-14) date/time syntax.
  If `s` cannot be converted, an error is thrown.

  For example,

      > Data.DateTime.fromString ('Wed, 2 July 2014 23:30:00 GMT');    // RFC2822 syntax
      Thu Jul 03 2014 01:30:00 GMT+0200 (CEST)

  Note, that the string is converted according to the local time zone.

---
unit
  function
name
  Data.DateTime.toIsoString
type
  Type.lambda ([DATETIME, STRING])
value
  function (d) { return d.toISOString(); }
info
  `Data.DateTime.toIsoString(d)` returns a string in [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) Extended Format, which has the form

      YYYY-MM-DDTHH:mm:ss.sssZ

  wheere `YYYY-MM-DD` is the date (e.g. `2014-07-02`), `T` is a constant belonging to the syntax, `HH:mm:ss.sss` is the time is seconds `ss` and milliseconds `sss`, and `Z` is a constant output here, standing for the UTC timezone.
  For example,

      > var d = Data.DateTime.now(null)
      undefined
      > d
      Wed Jul 02 2014 23:33:08 GMT+0200 (CEST)
      > d.toISOString()
      '2014-07-02T21:33:08.775Z'


---
unit
  function
name
  Data.DateTime.toLocaleString
type
  Type.lambda ([DATETIME, STRING])
value
  function (d) { return d.toLocaleString(); }
info
  ...
---
unit
  function
name
  Data.DateTime.toLocaleDateString
type
  Type.lambda ([DATETIME, STRING])
value
  function (d) { return d.toLocaleDateString(); }
info
  ...
---
unit
  function
name
  Data.DateTime.toLocaleTimeString
type
  Type.lambda ([DATETIME, STRING])
value
  function (d) { return d.toLocaleTimeString(); }
info
  ...
---
unit
  type
name
  Data.DateTime.DATETIME_RECORD
value
  undefined  // DUMMY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
comment
  The original value is this (but I don't understand what is going wrong!):

  Type.modelPlus ({
    year         : INT,
    month        : $range ([0, 11]),  // 0 is January, ..., 11 is December
    date         : $range ([1, 31]),  // for day of the month
  }) ({
    hours        : $range ([0, 23]),
    minutes      : $range ([0, 59]),
    seconds      : $range ([0, 59]),
    milliseconds : $range ([0, 999]),
    week         : $range ([1, 53]),
    day          : $range ([0, 6]),   // for day of the week, 0 is Sunday, ..., 6 is Saturday
    offset       : INT               // difference, in minutes, between UTC and local time
  })
info
  ...

  The `offset` is the [timezone offset](https://en.wikipedia.org/wiki/Time_zone#Time_zones_and_time_offsets), which is the difference between UTC and local time, given in minutes.
  The number is positive, if the current local time is behind UTC (e.g. Pacific Daylight Time), and negative, if the local time is ahead of UTC (e.g. Japan).
  For example, if the local timezone is UTC+10 (Australian Eastern Standard Time), the `offset` is `-600`.
---
unit
  function
name
  Data.DateTime.toLocaleRecord
type
  Type.lambda ([DATETIME, DATETIME_RECORD])
value
  function (d) {
    return Rec.create ({
      year         : d.getFullYear (),
      month        : d.getMonth (),
      date         : d.getDate (),
      hours        : d.getHours (),
      minutes      : d.getMinutes (),
      seconds      : d.getSeconds (),
      milliseconds : d.getMilliseconds (),
      week         : getWeek (d),
      offset       : d.getTimezoneOffset (),
    });
  }
info
  For example, on a machine in Amsterdam (Netherlands, so 1 hour ahead of UTC) and at summer time (another hour ahead of UTC), I obtain

      > var d = Data.DateTime.now()
      undefined
      > Data.DateTime.toIsoString(d)
      '2014-07-03T18:14:40.465Z'
      > Data.DateTime.toLocaleRecord (d)
      { year: 2014,
        month: 6,            // July
        date: 3,
        hours: 20,
        minutes: 14,
        seconds: 40,
        milliseconds: 465,
        week: 27,
        offset: -120 }       // two hours ahead of UTC

---
unit
  function
name
  Data.DateTime.toUtcRecord
type
  Type.lambda ([DATETIME, DATETIME_RECORD])
value
  function (d) {
    return Rec.create ({
      year         : d.getUTCFullYear (),
      month        : d.getUTCMonth (),
      date         : d.getUTCDate (),
      hours        : d.getUTCHours (),
      minutes      : d.getUTCMinutes (),
      seconds      : d.getUTCSeconds (),
      milliseconds : d.getUTCMilliseconds (),
      week         : getWeek (d),
      offset       : 0,
    });
  }
info
  For example, on a machine in Amsterdam (Netherlands, so 1 hour ahead of UTC) and at summer time (another hour ahead of UTC), I obtain

      > var d = Data.DateTime.now()
      undefined
      > Data.DateTime.toIsoString(d)
      '2014-07-03T18:14:40.465Z'
      > Data.DateTime.toLocaleRecord (d)
      { year: 2014, month: 6, date: 3, hours: 20, minutes: 14, seconds: 40, milliseconds: 465, week: 27, offset: -120 }
      > Data.DateTime.toUtcRecord (d)
      { year: 2014, month: 6, date: 3, hours: 18, minutes: 14, seconds: 40, milliseconds: 465, week: 27, offset: 0 }
---
unit
  function
name
  Data.DateTime.fromRecord
type
  Type.lambda ([DATETIME_RECORD, DATETIME])
value
  function (r) {
    // the mandatory part of the date-time record `r`
    var year  = r.year;
    var month = r.month;
    var date  = r.date;
    // the optional part of `r`
    var hours = r.hours || 0;
    var minutes = r.minutes || 0;
    var seconds = r.seconds || 0;
    var milliseconds = r.milliseconds || 0;
    var offset = r.offset || 0;
    // correct the minutes by the offset
    minutes = minutes + offset;
    // define and return the result
    var dateTime = new Date (
      year,
      month,
      date,
      hours,
      minutes + offset,
      seconds,
      milliseconds
    );
    return dateTime;
  }
info
  .....
---
unit
  function
name
  Data.DateTime.normalRecord
type
  Type.lambda ([DATETIME_RECORD, DATETIME_RECORD])
value
  function (r) { return toUtcRecord (fromRecord (r)); }
info
  For example,

      ....
---
// End Data.DateTime ///////////////////////////////////////////////////////////////////////////////////
---














---
// Data.Rex
---
unit
  doc
name
  Data
header
  Regular Expressions
---
unit
  type
name
  Data.REGULAR_EXPRESSION
value
  Type.object (RegExp)
---
unit
  struct
name
  Data.Rex
---
unit
  doc
name
  Data.Rex
header
  Construction and deconstruction of regular expressions
---
unit
  function
name
  Data.Rex.create
type
  Type.lambda ([STRING, STRING, REGULAR_EXPRESSION])
value
  function (pattern) {
    return function (flags) {
      return new RegExp (pattern, flags);
    }
  }
info
  `Data.Rex.create(pattern)(flags)` returns the regular expression object, made of the given `pattern` and `flags`.
---
unit
  function
name
  Data.Rex.pattern
type
  Type.lambda ([REGULAR_EXPRESSION, STRING])
value
  function (regex) {
    return regex.source;
  }
info
  .....
---
unit
  function
name
  Data.Rex.flags
value
  function (regex) {
    var flags = '';
    if (regex.global)     { flags += 'g'; }
    if (regex.ignoreCase) { flags += 'i'; }
    if (regex.multiline)  { flags += 'm'; }
    if (regex.sticky)     { flags += 'y'; }
    return flags;
  }
info
  ....
---
unit
  doc
name
  Data.Rex
header
  Functions on regular expressions
---
unit
  function
name
  Data.Rex.search
type
  Type.lambda ([STRING, REGULAR_EXPRESSION, INT])
value
  function (str) {
    return function (regex) {
      return str.search (regex);
    }
  }
info
  `Data.Rex.search(str)(regex)` returns the index of the first match of the `regex` inside the `str`. If there is no match, the result is `-1`.
---
unit
  function
name
  Data.Rex.replace
type
  Type.lambda ([STRING, REGULAR_EXPRESSION, STRING, STRING])
value
  function (str) {
    return function (regex) {
      return function (newStr) {
        return str.replace (regex, newStr);
      }
    }
  }
info
  `Data.Rex.replace(str)(regex)(newStr)` returns the string `str`, where each match of `regex` in `str` is replaced by the `newStr`.
---
unit
  function
name
  Data.Rex.match
type
  Type.lambda ([STRING, REGULAR_EXPRESSION, Type.nullify (ARRAY)])
value
  function (str) {
    return function (regex) {
      return str.match (regex);
    }
  }
info
  .....

  See also the native [`String::match`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match) method.
---
unit
  function
name
  Data.Rex.exec
type
  Type.lambda ([REGULAR_EXPRESSION, STRING, Type.nullify (ARRAY)])
value
  function (regex) {
    return function (str) {
      return regex.exec (str);
    }
  }
info
  .....
---
unit
  function
name
  Data.Rex.test
type
  Type.lambda ([REGULAR_EXPRESSION, STRING, BOOLEAN])
value
  function (regex) {
    return function (str) {
      return regex.test (str);
    }
  }
info
  .....
---
---
// end Data.Rex
---







---
// Data.Math
---
unit
  doc
name
  Data
header
  The built-in `Math` values and functions
---
unit
  struct
name
  Data.Maths
---
unit
  doc
name
  Data.Maths
header
  Standard floating-point numbers
info
  The are mainly the functions from the native ECMAScript [`Math`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) object.
---
unit
  value
name
  Data.Maths.pi
type
  NUMBER
value
  Math.PI
info
  `Data.Maths.pi` is the number [&pi;](https://en.wikipedia.org/wiki/Pi), the ratio of a circle's circumfence to its diameter.

      > Data.Maths.pi
      3.141592653589793

  `Data.Maths.pi` is the same and implemented as the native ECMAScript value `Math.PI`.
  We changed the `PI` to `pi` to comply with the TofJs rules for naming values.
---
unit
  value
name
  Data.Maths.e
type
  NUMBER
value
  Math.E
info
  `Data.Maths.e` is [Eulers's constant](https://en.wikipedia.org/wiki/E_(mathematical_constant)).

      > Data.Maths.e
      2.718281828459045

  `Data.Maths.e` is the same and implemented as the native ECMAScript value `Math.E`.
  We changed the `E` to `e` to comply with the TofJs rules for naming values.
---
unit
  value
name
  Data.Maths.ln2
type
  NUMBER
value
  Math.LN2
info
  `Data.Maths.ln2` is the natural logarithm of `2`.

      > Data.Maths.ln2
      0.6931471805599453

  `Data.Maths.ln2` is the same and implemented as the native ECMAScript value `Math.LN2`.
  We changed the identifier `LN2` to `ln2` to comply with the TofJs rules for naming values.
---
unit
  value
name
  Data.Maths.ln10
type
  NUMBER
value
  Math.LN10
info
  `Data.Maths.ln10` is the natural logarithm of `10`.


      > Data.Maths.ln10
      2.302585092994046

  `Data.Maths.ln10` is the same and implemented as the native ECMAScript number `Math.LN10`.
  We changed the identifier `LN10` to `ln10` to comply with the TofJs rules for naming values.
---
unit
  value
name
  Data.Maths.log2e
type
  NUMBER
value
  Math.LOG2E
info
  `Data.Maths.log2e` is the base `2` logarithm of `e` (i.e. [`Data.Maths.e`](#Data.Maths.e)).

      > Data.Maths.log2e
      1.4426950408889634

  `Data.Maths.log2e` is the same and implemented as the native ECMAScript number `Math.LOG2E`.
  We changed the identifier `LOG2E` to `log2e` to comply with the TofJs rules for naming values.
---
unit
  value
name
  Data.Maths.log10e
type
  NUMBER
value
  Math.LOG10E
info
  `Data.Maths.log10e` is the base `10` logarithm of `e` (i.e. [`Data.Maths.e`](#Data.Maths.e)).

      > Data.Maths.log10e
      0.4342944819032518

  `Data.Maths.log10e` is the same and implemented as the native ECMAScript number `Math.LOG10E`.
  We changed the identifier `LOG10E` to `log10e` to comply with the TofJs rules for naming values.
---
unit
  value
name
  Data.Maths.sqrt2
type
  NUMBER
value
  Math.SQRT2
info
  `Data.Maths.sqrt2` is the square root of `2`.

      > Data.Maths.sqrt2
      1.4142135623730951
---
unit
  value
name
  Data.Maths.sqrt1_2
type
  NUMBER
value
  Math.SQRT1_2
info
  `Data.Maths.sqrt1_2` is the square root of `1/2`, i.e. the inverse `1/Data.Maths.sqrt2` of the square root of `2`.

      > Data.Maths.sqrt1_2
      0.7071067811865476
---
unit
  doc
name
  Data.Maths
header
  Standard functions on floating-point numbers
info
  For a summary of the properties of the `Math` object, see the [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math).
---
unit
  function
name
  Data.Maths.abs
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.abs
info
  `Data.Maths.abs(x)` returns the absolute value of `x`.
---
unit
  function
name
  Data.Maths.acos
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.acos
info
  `Data.Maths.acos(x)` returns the arccosine of `x`.
---
unit
  function
name
  Data.Maths.acosh
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.acosh
info
  `Data.Maths.acosh(x)` returns the hyperbolic arccosine of `x`.
---
unit
  function
name
  Data.Maths.asin
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.asin
info
  `Data.Maths.asin(x)` returns the arcsine of `x`.
---
unit
  function
name
  Data.Maths.asinh
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.asinh
info
  `Data.Maths.asinh(x)` returns the hyperbolic arcsine of `x`.
---
unit
  function
name
  Data.Maths.atan
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.atan
info
  `Data.Maths.atan(x)` returns the arctangent of `x`.
---
unit
  function
name
  Data.Maths.atanh
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.atanh
info
  `Data.Maths.atanh(x)` returns the hyperbolic arctangent of a number.
---
unit
  function
name
  Data.Maths.atan2
type
  Type.lambda ([NUMBER, NUMBER, NUMBER])
value
  function (y) {
    return function (x) {
      return Math.atan2 (y, x);
    }
  }
info
  `Data.Maths.atan2(y)(x)` returns the aractangent of the quotient of its arguments
---
unit
  function
name
  Data.Maths.cbrt
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.cbrt
info
  `Data.Maths.cbrt(x)` returns the cube root of `x`.
---
unit
  function
name
  Data.Maths.ceil
type
  Type.lambda ([NUMBER, INT])
value
  Math.ceil
info
  `Data.Maths.ceil(x)` returns the smallest integer greater than or equal to `x`.
comment
  see also `Int.ceil`
---
unit
  function
name
  Data.Maths.clz32
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.clz32
info
  `Data.Maths.clz32(x)` returns the number of leading zeroes of a 32-bit integer.
comment
  Maybe, this should also go to `Data.Bit.clz32`.
---
unit
  function
name
  Data.Maths.cos
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.cos
info
  `Data.Maths.cos(x)` returns the cosine of `x`.
---
unit
  function
name
  Data.Maths.cosh
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.cosh
info
  `Data.Maths.cosh(x)` returns the hyperbolic cosine of `x`.
---
unit
  function
name
  Data.Maths.exp
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.exp
info
  `Data.Maths.exp(x)` returns `e^x`, where `e` is Euler's constant (`2.718...`, see [`Data.Maths.e`](#Data.Maths.e).
---
unit
  function
name
  Data.Maths.expm1
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.expm1
info
  `Data.Maths.expm1(x)` returns `e^x-1`, i.e. `Data.Maths.exp(x) - 1`.
---
unit
  function
name
  Data.Maths.floor
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.floor
info
  `Data.Maths.floor(x)`  returns the largest integer less than or equal to `x`.
info
  see `Int.floor`
---
unit
  function
name
  Data.Maths.fround
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.fround
info
  `Data.Maths.fround(x)` returns the nearest [single precision](http://en.wikipedia.org/wiki/Single-precision_floating-point_format) float representation of `x`.
---
unit
  function
name
  Data.Maths.hypot
type
  Type.lambda ([Type.list (NUMBER), NUMBER])
value
  Math.hypot
info
  `Data.Maths.hypot([x_1,...,x_n])` returns the square root of the sum of squares of its argument.
---
unit
  function
name
  Data.Maths.imul
type
  Type.lambda ([NUMBER, NUMBER, NUMBER])
value
  Math.imul
info
  `Data.Maths.imul(x)(y)` returns the result of a 32-bit integer multiplication.
comment
  Maybe, this should be moved to `Int` or `Data.Bit`??
---
unit
  function
name
  Data.Maths.log
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.log
info
  `Data.Maths.log(x)` returns the natural logarithm of `x`.
---
unit
  function
name
  Data.Maths.log1p
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.log1p
info
  `Data.Maths.log1p(x)` returns the natural logarithm of `x+1`.
---
unit
  function
name
  Data.Maths.log10
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.log10
info
  `Data.Maths.log10(x)` returns the base 10 logarithm of `x`.
---
unit
  function
name
  Data.Maths.log2
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.log2
info
  `Data.Maths.log2(x)` returns the binary logarithm of `x`.
---
unit
  function
name
  Data.Maths.max
type
  Type.lambda ([Type.list (NUMBER), NUMBER])
value
  function (xL) {
    return Math.max.apply (null, xL);
  }
info
  `Data.Maths.max([x_1,...,x_n])` returns the greatest of the number `x_1`,...,`x_n`.
comment
  see `Num.max` and `Num.maximum`
---
unit
  function
name
  Data.Maths.min
type
  Type.lambda ([Type.list (NUMBER), NUMBER])
value
  function (xL) {
    return Math.min.apply (null, xL);
  }
info
  `Data.Maths.min([x_1,...,x_n]) returns the smallest of the numbers `x_1`,...,`x_n`.
comment
  see `Num.mim` and `Num.minimum`
---
unit
  function
name
  Data.Maths.pow
type
  Type.lambda ([NUMBER, NUMBER, NUMBER])
value
  function (x) {
    return function (y) {
      return Math.pow (x) (y);
    }
  }
info
  `Data.Maths.pow(x)(y)` returns base `x` to the exponent power `y`.
---
unit
  function
name
  Data.Maths.round
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.round
info
  `Data.Maths.round(x)` returns the value of a number rounded to the nearest integer.
comment
  See `Int.round`
---
unit
  function
name
  Data.Maths.sign
type
  Type.lambda ([NUMBER, Type.finite ([-1,-0,0,1])])
value
  Math.sign
info
  `Data.Maths.sign(x)` returns the sign of `x`, i.e.

  * `-1`, if `x` is negative
  * `-0`, if `x` is negative zero
  * `0`, if `x` is (positive) zero
  * `1`, if `x` positive

  The [real numbers](https://en.wikipedia.org/wiki/Real_number) only have one zero element `0`, and every bigger element is positive, i.e. signature `1`, and every smaller element is negative with signature `-1`. Accordingly, the __signature__ of every real number is either `-1`, `0`, or `1`.
  Each real number `x` can be decomposed into its __signature__ `sign(x)` and __absolute value__ `abs(x)`, where

      x === sign(x) * abs(x)

  But the [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point) floating point standard has two zeros `0` and `-0`. And actually, they are really different values, because they can lead to different results:

      > 7 / 0
      Infinity

      > 7 / -0
      -Infinity

  Accordingly, the signature of a floating point number is not one of three, but one of the four values `-1`, `-0`, `0` or '1`.

comment
  The implementation is as [`Math.sign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign), introduced in ES6.

  The polyfill for `Math.sign` on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign) is suggested as

      Math.sign = Math.sign || function(x) {
        x = +x; // convert to a number
        if (x === 0 || isNaN(x)) {
          return x;
        }
        return x > 0 ? 1 : -1;
      }
---
unit
  function
name
  Data.Maths.sin
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.sin
info
  `Data.Maths.sin(x)` returns the sine of `x`.
---
unit
  function
name
  Data.Maths.sinh
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.sinh
info
  `Data.Maths.sinh(x)` returns the hyperbolic sine of `x`.
---
unit
  function
name
  Data.Maths.sqrt
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.sqrt
info
  `Data.Maths.sqrt(x)` returns the square root of `x`.
---
unit
  function
name
  Data.Maths.tan
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.tan
info
  `Data.Maths.tan(x)` returns the tangent of `x`.
---
unit
  function
name
  Data.Maths.tanh
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.tanh
info
  `Data.Maths.tanh(x)` returns the hyperbolic tangent of `x`.
---
unit
  function
name
  Data.Maths.trunc
type
  Type.lambda ([NUMBER, NUMBER])
value
  Math.trunc
info
  `Data.Maths.trunc(x)` returns the integral part of `x`, removing any fractional digits.
---
---
unit
  doc
name
  Data.Maths
header
  Random floating point numbers
---
unit
  function
name
  Data.Maths.random
type
  Type.fun ([NULL, NUMBER])
value
  function (x) { return Math.random(); }
info
  `Data.Maths.random(null)` returns a pseudo-random number between 0 and 1.
---

---
// end Data.Maths
---











---
// Data.Json
---
---
unit
  doc
name
  Data
header
  JSON (JavaScript Object Notation)
---
---
unit
  struct
name
  Data.Json
---
---
unit
  doc
name
  Data.Json
header
  JSON values, JSON code, and their mutual conversion
---
---
unit
  type
name
  Data.Json.VALUE
value
  Type.fromRecord ({
    complain:
      function (x) {
        var y = JSON.stringify (JSON.parse (x));
        if (Any.equal (x) (y)) { return ''; }
        else                   { return "The value is not a JSON value."; }
      },
    name:
      'Data.Json.VALUE',
    cardinality:
      function () { return null; }
  })
info
  ...
comment
  IMPROVE THE IMPLEMENTATION!!!
---
unit
  type
name
  Data.Json.CODE
value
  STRING // dummy!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
info
  ...
comment
  IMPROVE THE IMPLEMENTATION!!!!!!!!!!!!!!!!1
---
unit
  function
name
  Data.Json.code2value
type
  Type.lambda ([CODE, VALUE])
value
  function (code) {
    try {
      return JSON.parse (code);
    } catch (e) {
      throw Error ("Unable to convert the JSON code into a JSON value: " + e);
    }
  }
info
  .....
---
unit
  function
name
  Data.Json.value2code
type
  Type.lambda ([VALUE, CODE])
value
  function (x) {
    try {
      return JSON.stringify (x, null, 2);
    } catch (e) {
      throw Error ("Unable to convert the JSON value into JSON code: " + e);
    }
  }
info
  .....
---
---
unit
  doc
name
  Data.Json
header
  Functions on JSON values
---
---
unit
  function
name
  Data.Json.urtype
type
  Type.lambda ([Json.VALUE, URTYPE])
value
  function (x) {
    switch (typeof x) {
      case 'boolean':
        return BOOLEAN;
      case 'number':
        return NUMBER;
      case 'string':
        return STRING;
      case 'object':
        if (x === null) {
          return NULL;
        } else if (Array.isArray (x)) {
          return LIST;
        } else {
          return RECORD;
        }
      default:
        throw Error ("The given `" + (typeof x) + "` value is not a JSON value.");
    }
  }
info
  Each JSON value is exactly of one of the following urtypes: `NULL`, `BOOLEAN`, `NUMBER`, `STRING`, `LIST`, or `RECORD`.
  `Data.Json.urtype (x)` returns this urtype for the given JSON value `x`.

  For example,


---
unit
  function
name
  Data.Json.compare
type
  Type.lambda ([Json.VALUE, Json.VALUE, Type.finite ([-1,0,1])])
value
  function (x) {
    return function (y) {
      return ".......................................Data.Json.compare(x)(y).........................................";
    }
  }
info
  `Data.Json.compare` induces a [linear order] on the set of all JSON values.

  `Data.Json.compare(x)(y)` is `-1`, `0`, or `1`, depending on whether `x` is smaller, equal, or bigger than `y`.
---
unit
  function
name
  Data.Json.equal
type
  Type.lambda ([Json.VALUE, Json.VALUE, BOOLEAN])
value
  function (x) {
    return function (y) {
      return ".............................Data.Json.equal(x)(y)...................................................";
    }
  }
info
  .....
---
unit
  function
name
  Data.Json.comparisonValue
type
  Type.lambda ([Json.VALUE, Json.VALUE, Json.VALUE])
value
  function comparisonValue (x) {
    return function (y) {
      if (x === y) {
        return 0;
      } else {
        if (Type.chi (LIST) (x) && Type.chi (LIST) (y)) {
          var zL = [];
          var isEqual = true;
          for (var i = 0; i < Math.min (x.length, y.length); i++) {
            var t = comparisonValue (x[i]) (y[i]);
            if (typeof t === 'number' && t < 0) { isEqual = false; }
            zL.push (t);
          }
          if (x.length > y.length) {
            for (var i = 0; i < x.length - y.length; i++) {
              zL.push (1);
            }
            return zL;
          } else if (x.length < y.length) {
            for (var i = 0; i < y.length - x.length; i++) {
              zL.push (2);
            }
            return zL;
          } else {
            if (isEqual) { return 0; }
            else         { return zL; }
          }
        } else if (Type.chi (RECORD) (x) && Type.chi (RECORD) (y)) {
          var o = {};
          var isEqual = true;
          for (var k in x) {
            if (k in y) {
              var t = comparisonValue (x[k]) (y[k]);
              if (typeof t === 'number' && t < 0) { isEqual = false; }
              o [k] = t;
            } else {
              isEqual = false;
              o [k] = 1;
            }
          }
          for (var k in y) {
            if (! (k in x)) {
              isEqual = false;
              o [k] = 2;
            }
          }
          if (isEqual) { return 0; }
          else         { return Rec.create (o); }
        } else {
          return -1;
        }
      }
    }
  }
info
  `Data.Json.comparison (x) (y)` is a value which is recursively defined to be one of the following:

  * either a primitive value, namely one of `-1` (for "not equal"), `0` (for "equal"),
  * a list of those values
  * a record of those value.

  For example,

      > Data.Json.comparisonValue (123.456) (123.456)
      0

      > Data.Json.comparisonValue ("Hello") ("Hello")
      0

      > Data.Json.comparisonValue ('Hi there!') (123.456)
      -1

      > Data.Json.comparisonValue (false) (null)
      -1

      > Data.Json.comparisonValue (['a', 'b', 'c']) ('Hello')
      -1

      > Data.Json.comparisonValue (['a', 'b', 'c', 'd', 'e']) (['a', 'b', 'x'])
      [ 0, 0, -1, 1, 1 ]

      > Data.Json.comparisonValue (['a', 'b', 'c']) (['a', 'b', 'c'])
      0

      > Data.Json.comparisonValue ({one: 123, three: 234, four: 345}) ({two: 123, three: 234, four: 789})
      { one: 1, three: 0, four: -1, two: 2 }

      > Data.Json.comparisonValue ({}) ({one: 123, two: 234})
      { one: 2, two: 2 }

      > Data.Json.comparisonValue ({one: null, two: [3,2,1]}) ({one: null, two: [1,2,3,4]})
      0

      > Data.Json.comparisonValue ({one: false, two: [1,2]}) ({one: false, two: [1,2]})
      0

/***
Data.Json.comparisonValue (123.456) (123.456)
Data.Json.comparisonValue ("Hello") ("Hello")
Data.Json.comparisonValue ('Hi there!') (123.456)
Data.Json.comparisonValue (false) (null)
Data.Json.comparisonValue (['a', 'b', 'c']) ('Hello')
Data.Json.comparisonValue (['a', 'b', 'c', 'd', 'e']) (['a', 'b', 'x'])
Data.Json.comparisonValue (['a', 'b', 'c']) (['a', 'b', 'c'])
Data.Json.comparisonValue ({one: 123, three: 234, four: 345}) ({two: 123, three: 234, four: 789})
Data.Json.comparisonValue ({}) ({one: 123, two: 234})
Data.Json.comparisonValue ({one: null, two: [3,2,1]}) ({one: null, two: [1,2,3,4]})
Data.Json.comparisonValue ({one: false, two: [1,2]}) ({one: false, two: [1,2]})

  .....
***/

---
---
// end Data.Json
---









---
// Url and Uri
---
unit
  doc
name
  Data
header
  URL's and URI's
---
unit
  type
name
  Data.URL
value
  Type.subType
    (STRING)
    (function (s) {
      if (Data.Url.regex.test (s)) { return ""; } else { return "Not a valid URL: `" + Any.ellipsis(s) + "`."; };
    })
info
  A [Uniform Resource Locator](http://en.wikipedia.org/wiki/Uniform_resource_locator) has the following syntax:
  <blockquote>
    <span style="color:green">scheme_name</span>:<span style="color:green">hierarchical_part</span>?<span style="color:green">query</span>#<span style="color:green">fragment</span>
  </blockquote>

  ... see [here](http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax) ...

      ....................

  For example,

      ....................
comment
  Integrate this [demo page](https://mathiasbynens.be/demo/url-regex) as a session.
---
unit
  struct
name
  Data.Url
info
  Implement something like
  the [URL module in Node.js](http://nodejs.org/api/url.html)
  or the [Location object](http://www.w3schools.com/jsref/obj_location.asp) in the DOM.
comment
  IMPLEMENT THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!!
---
unit
  value
name
  Data.Url.regex
value
  new RegExp(
    "^" +
      // protocol identifier
      "(?:(?:https?|ftp)://)" +
      // user:pass authentication
      "(?:\\S+(?::\\S*)?@)?" +
      "(?:" +
        // IP address exclusion
        // private & local networks
        "(?!(?:10|127)(?:\\.\\d{1,3}){3})" +
        "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +
        "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
        // IP address dotted notation octets
        // excludes loopback network 0.0.0.0
        // excludes reserved space >= 224.0.0.0
        // excludes network & broacast addresses
        // (first & last IP address of each class)
        "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
        "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
        "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
      "|" +
        // host name
        "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
        // domain name
        "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
        // TLD identifier
        "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
      ")" +
      // port number
      "(?::\\d{2,5})?" +
      // resource path
      "(?:/\\S*)?" +
    "$", "i"
  );
info
  This regular expression is a copy from [Diego Perini](https://gist.github.com/dperini/729294) from 2010/12/05.
---
---
---
unit
  struct
name
  Data.Uri
info
  This structure

  * redefines four [global JavaScript functions](http://www.w3schools.com/jsref/jsref_obj_global.asp)
    `decodeURI`, `encodeURI`, `decodeURIComponent` and `encodeURIComponent`.

  * defines an encoding/decoding pair of functions to turns string records (with optional `null` values) into a query
    string part of a URL, and vice versa.
    For example, the record `{one: "aaa", two: "bbb", three: "ccc"}` turns into `one=aaa&two=bbb&three=ccc`.
---
unit
  function
name
  Data.Uri.encode
type
  Type.lambda ([STRING, STRING])
value
  encodeURI
comment
  In the table below, I write "dollar sign", because actually writing the dollar sign results in strange compiler errors.
info
  `Uri.encode(s)` encodes a [Uniform Resource Identifier](http://en.wikipedia.org/wiki/Uniform_resource_identifier) (URI)
   `s` by replacing each instance of certain characters by one, two, three, or four escape sequences representing the
  [UTF-8](http://en.wikipedia.org/wiki/UTF-8) encoding of the character.

  For example,

      > Data.Uri.encode ('Schöne neue Welt!')
      'Sch%C3%B6ne%20neue%20Welt!'

      > encodeURI ('A λχ-type-system')
      'A%20%CE%BB%CF%87-type-system'

      > decodeURI (encodeURI ('A λχ-type-system'))
      'A λχ-type-system'

  `Data.Uri.encode` replaces all characters except the following with the appropriate [UTF-8](http://en.wikipedia.org/wiki/UTF-8)
  escape sequences:

      Type                       Includes
      -------------------------  -------------------------------------------------------------------
      reserved characters        `; , / ? : @ & = +` and dollar sign
      unescaped characters       alphabetic, decimal digits, and these ones: `- _ . ! ~ * ' ( )`
      score                      `#`

  Note that `Data.Uri.encode` by itself cannot form proper HTTP GET and POST requests, such as for XMLHTTPRequests, because
  `&`, `+`, and `=` are not encoded, which are treated as special characters in GET and POST requests.
  `Uri.encodeComponent`, however, does encode these characters.

  For example,

      > Data.Uri.encode ('http://localhost:55555/foo/bar?greeting=Hello world!&price=$500')
      'http://localhost:55555/foo/bar?greeting=Hello%20world!&price=$500'

      > Data.Uri.encodeComponent ('http://localhost:55555/foo/bar?greeting=Hello world!&price=$500')
      'http%3A%2F%2Flocalhost%3A55555%2Ffoo%2Fbar%3Fgreeting%3DHello%20world!%26price%3D%24500'

  `Data.Uri.encode` is implemented as a redefinition of the global
  [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
  function.
---
unit
  function
name
  Data.Uri.decode
type
  Type.lambda ([STRING, STRING])
value
  decodeURI
info
  `Data.Uri.decode(s)` decodes a [Uniform Resource Identifier](http://en.wikipedia.org/wiki/Uniform_resource_identifier) (URI)
   `s` previously creaed by `Data.Uri.encode(x)` or by a similar routine.

  For example,

      > Data.Uri.encode ('A λχ-type-system')
      'A%20%CE%BB%CF%87-type-system'

      > Data.Uri.decode ('A%20%CE%BB%CF%87-type-system')
      'A λχ-type-system'

  `Data.Uri.decode(s)` replaces each escape sequence in the encoded URI `s` with the character that it represents, but does not decode escape sequences that could not have been introduced by `Uri.encode`.
  The character `#` is not decoded from escape sequences.

  `Data.Uri.decode` is implemented as a redefinition of the global
  [`decodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI)
  function.
---
unit
  function
name
  Data.Uri.encodeComponent
type
  Type.lambda ([STRING, STRING])
value
  encodeURIComponent
info
  `Data.Uri.encodeComponent(s)` encodes a [Uniform Resource Identifier](http://en.wikipedia.org/wiki/Uniform_resource_identifier)
  (URI) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing
  the [UTF-8](http://en.wikipedia.org/wiki/UTF-8) encoding of the character.

  It escapes all characters except the following: alphabetic, decimal, digits, `-`, `_`, `.`, `!`, `~`, `*`, `'`, `(`, `)`.

  `Data.Uri.encodeComponent` is implemented as a redefinition of the global
  [`encodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
  function.

  For example,

      > Data.Uri.encodeComponent ('http://localhost:55555/foo/bar?greeting=Hello world!&price=$500')
      'http%3A%2F%2Flocalhost%3A55555%2Ffoo%2Fbar%3Fgreeting%3DHello%20world!%26price%3D%24500'

---
unit
  function
name
  Data.Uri.decodeComponent
type
  Type.lambda ([STRING, STRING])
value
  decodeURIComponent
info
  `Data.Uri.decodeComponent(s)` decodes a [Uniform Resource Identifier](http://en.wikipedia.org/wiki/Uniform_resource_identifier)
  (URI) component `s` previously created by `Uri.encodeComponent(x)` or by a similar routine.

  `Data.Uri.decodeComponent` is implemented as a redefinition of the global
  [`decodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent)
  function.

  For example,

      ......
---
unit
  function
name
  Data.Uri.record2queryString
type
  Type.lambda ([Type.record (Type.nullify (STRING)), STRING])
value
  function (r) {
    var strL = [];
    for (var k in r) {
      if (Type.chi (STRING) (r [k])) {
        strL.push (k + "=" + encodeComponent (r [k]));
      } else if (Type.chi (NULL) (r [k])) {
        strL.push (k);
      } else {
        throw Error ( "`Data.Uri.record2queryString(r)` error, `r` is not a nullified string record, its `"
                    + k + "` value `" + r[k] + "` is neither a string nor `null`." );
      }
    }
    return strL.join ("&");
  }
info
  `Data.Uri.record2queryString(r)` converts the record `r` that has either string or `null` values into a
  [query string](http://en.wikipedia.org/wiki/Query_string).

  The conversion rules are:

  * each key-value pair `k:v` of the record is converted into a string `k=w`, where `w` is the URI-encoded value `v`.
  * each key `k` with value `null` is converted into `k`, again.
  * all there strings are joined with the `&` as separation symbol.

  For example,

      > Data.Uri.record2queryString ({first: '123', second: null, third: "Hello World!"})
      'first=123&second&third=Hello%20World!'

      > Data.Uri.record2queryString({})
      ''

      > Data.Uri.record2queryString ({one:'123', two: null, three: 'null'})
      'one=123&two&three=null'

      > Data.Uri.record2queryString ({one: 123})
      Error: ....

      > Data.Uri.record2queryString ({greeting: "Hello there!", smiley: ":-)"})
      'greeting=Hello%20there!&smiley=%3A-)'

---
unit
  function
name
  Data.Uri.queryString2record
type
  Type.lambda ([STRING, Type.record (STRING)])
value
  function (s) {
    var r = {};
    if (s.length > 0) {
      var strL = s.split ("&");
      for (var i = 0; i < strL.length; i++) {
        var pair  = strL[i].split ('=');
        var key   = pair[0];
        var value = pair[1];
        value = ( value
                ? decodeComponent (value)
                : null );
        r[key] = value;
      }
    }
    return Rec.create (r);
  }
info
  `Data.Uri.queryString2record(s)` decodes the query string `s` into the original record `r`, so that `Uri.record2queryString(r)` is `s`, again.

  For example,

      > Data.Uri.queryString2record ('first=123&second&third=Hello%20World!')
      { first: '123', second: null, third: 'Hello World!' }

  Note, that

      > Data.Uri.queryString2record ('first&second=&third=null&=foo')
      { first: null, second: '', third: 'null', '': 'foo' }

  which means that

  * a key without a value (`first`) turns into a null value (`first: null`)
  * a key with empty value (`second=`) turns into null value (`second: null`).
  * a null value (`third=null`) turns into a string value (`third: 'null'`)
  * an empty key (`=foo`) turns into the empty string key (`'': 'foo')

---
---
// end Url and Uri
---



---
---
unit
  doc
name
  Data
header
  Email
---
---
unit
  struct
name
  Data.Email
---
---
unit
  type
name
  Data.Email.ADDRESS
value
  Type.regularString ( '^\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$' )
info
  `Data.Email.ADDRESS` is the type of all email addresses.

  For example,

      > Type.chi (Data.Email.ADDRESS) ('somebody@example.com');
      true

      > Type.chi (Data.Email.ADDRESS) ('somebody@example');
      false

      > Type.chi (Data.Email.ADDRESS) ('example.com');
      false

  The type is implemented by a regular expression, but one that is a little too simple to match all actually valid email addresses.
  See the [wikipedia](https://en.wikipedia.org/wiki/Email_address) entry for more information.
---
---
// end Data.Email
---
---










---
unit
  doc
name
  Data
header
  Maps and Sets
---


---
---
// Data.Map
---
---
unit
  struct
name
  Data.Map
info
  see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
---
---
unit
  doc
name
  Data.Map
header
  ...........CONTINUEHERE TO IMPLEMENT MAPS.................................
---
---
// end Data.Map
---


---
---
// Data.Set
---
---
unit
  struct
name
  Data.Set
info
  see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
---
unit
  doc
name
  Data.Set
header
  .............CONTINUEHERE TO IMPLEMENT SETS..............
---
---
// end Data.Set
---












---
---
unit
  doc
name
  Data
header
  **HTML, CSS and Markdown**
---
---


---
// Data.Html
---
---
unit
  doc
name
  Data
header
  HTML
---
---
unit
  type
name
  Data.HTML
value
  Type.synonym (STRING)
info
  .....
comment
  Insert `Html` from `html.tofu`.
---
unit
  struct
name
  Data.Html
---
unit
  doc
name
  Data.Html
header
  Native `String` methods
---
unit
  function
name
  Data.Html.anchor
type
  Type.lambda ([HTML, URL, HTML])
value
  function (h) {
    return function (href) {
      return h.anchor(href);
    }
  }
info
  `Data.Html.anchor(h)(href)` returns a HTML anchor element `<a>` that refers to the address `href`.
  For example,

      > Data.Html.anchor ('Look here!') ('http://example.com')
      '<a name="http://example.com">Look here!</a>'
---
unit
  doc
name
  Data.Html
header
  ........continuehere................
---
---

// Data.Html.anchor
// Data.Html.big
// Data.Html.blink
// Data.Html.bold
// Data.Html.fixed
// Data.Html.fontcolor
// Data.Html.fontsize
// Data.Html.italics
// Data.Html.link
// Data.Html.small
// Data.Html.strike
// Data.Html.sub
// Data.Html.sup


---
unit
  doc
name
  Data.Html
header
  More functions
---
---
unit
  function
name
  Data.Html.entityify
type
  Type.lambda ([STRING, STRING])
value
  function (str) {
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  };
info
  `Data.Html.entityify(str)` returns a mutation of the argument `str`, where the following replacements have taken place:

  character      replacement
  ----------     --------------
  `&`            `&amp;`
  `<`            `&lt;`
  `>`            `&gt;`
  `"`            `&quot;`

  For example,

      > Data.Html.entityify ('<h1> What is "Good & Bad"? </h1>')
      '&lt;h1&gt; What is &quot;Good &amp; Bad&quot;? &lt;/h1&gt;'

  `Data.Html.entityify` is similar to the [`htmlentities()`](http://us2.php.net/manual/en/function.htmlentities.php) function of [PHP](http://php.net/manual/en/).
---
unit
  doc
name
  Data.Html
header
  HTML Names [.............move this to Data.Name.............]
info
  A `NAME` value is a name according to the syntax rule of ECMAScript: it may contain the dollar sign `$` and it is case-sensitive.
  But names in HTML, i.e. values for the [`id` attribute](http://www.w3schools.com/tags/att_global_id.asp), are case-insensitive and must not contain `$`.
  For that reason, we define `HTML_NAME`s as a separate type together with conversions between them

                 toHtmlName
      NAME -------------------> HTML_NAME

                   fromHtmlName
      HTML_NAME -------------------> NAME

---
unit
  type
name
  Data.Html.HTML_NAME
value
  Type.subType (STRING) (function (s) {
      var rex = /^[A-Za-z][A-Za-z0-9-]*$/;
      if (rex.test (s)) {
        return "";
      } else {
        return ( "`" + s + "` is not a non-empty string, beginning with a letter and only comprising letters, digits and hyphens.")
      }
    }
  )
info
  A __HTML name__, i.e. a `HTML_NAME` value, is a non-empty string, only made of letters (`A`,...,`Z`,`a`,...,`z`), digits (`0`,`1`,...,`9`) and hyphens (`-`), and beginning with a letter.

  Examples of HTML names are:

      `"this-is-a-HTML-name"`   `"about-a-100-things"`   `"section-2-7"`

  Counterexamples are:

  * `"this is not a HTML name"` is not a HTML name, because it contains spaces
  * `"no_good_either"` is not a HTML name, because it contains underscores
  * `"1000-years"` is not a HTML name, because it does not start with a letter
  * `""` the empty string is not a HTML name.
  * `"abc*$def"` is not a HTML name, because it contains a `*` and a `$`

  Accordingly, we obtain

      > Data.Html.HTML_NAME.chi ("this-is-a-HTML-name")
      true
      > Data.Html.HTML_NAME.chi ("about-a-100-things")
      true
      > Data.Html.HTML_NAME.chi ("section-2-7")
      true
      > Data.Html.HTML_NAME.chi ("this is not a HTML name")
      false
      > Data.Html.HTML_NAME.chi ("1000-years")
      false
      > Data.Html.HTML_NAME.chi ("")
      false
      > Data.Html.HTML_NAME.chi ("abc*$def")
      false

  Note, that the [official HTML4 definition of ID and NAME tokens](http://www.w3.org/TR/html4/types.html#type-id) are more permissive than our `HTML_NAME` type: they must begin with a letter (`A`,...,`Z`,`a`,...,`z`) and may be followed by any number of letters, digits (`0`,...,`9`), hyphens (`-`), underscores (`_`), colons (`:`) and periods (`.`).
  [HTML5](http://www.w3.org/TR/html5/dom.html#the-id-attribute) is even more permissive and says it must start with an arbitrary character, followed by more characters, not containing space symbols.
  Our `HTML_NAME` definition is more restrictive, because it avoids problems when the names are used in other contexts, like CSS, where colons and periods have a special and different meaning.

  There is a nice stackoverflow post on the question [_What are vaid values for the id attribute in HTML?_](http://stackoverflow.com/questions/70579/what-are-valid-values-for-the-id-attribute-in-html)
---
unit
  function
name
  Data.Html.toHtmlName
type
  Type.lambda ([Global.NAME, HTML_NAME])
value
  function (name) {
    if (name === '') { return 'ROOT'; }
    var htmlName = name . replace (/\$/g, "DOLLAR") . replace (/\./g, "-");
    if (htmlName === '') {
      throw Error ("`Data.Html.toHtmlName(name)` error, the conversion leaves an empty string for the given argument `" + name + "`.");
    } else {
      return htmlName;
    }
  }
info
  `Data.Html.toHtmlName("")`, the HTML name of the empty name is `'ROOT'`.

  Otherwise, `Data.Html.toHtmlName(name)` is generated as follows:
  Each dot `.` is replaced by a hyphen `-` and each dollar sign `$` is replaced by the word `DOLLAR`.
  If the result would leave an empty string, an error is thrown.

  For example

      Data.Html.toHtmlName ('One_One.TwoTwo.$Three')  ===  "One_One-TwoTwo-DOLLARThree"

  Note, that a `NAME` may be an empty string, but a `HTML_NAME` must always be non-empty.
comment
  UPDATE/CHANGE THIS!!! The `$` conversion is obsolete!!!
---
unit
  function
name
  Data.Html.fromHtmlName
type
  Type.lambda ([HTML_NAME, Global.NAME])
value
  function (htmlName) {
    if (htmlName === 'ROOT') { return ''; }
    var name = htmlName . replace ("DOLLAR", "\u0024") . replace (new RegExp ('-', 'g'), ".");
    return name;
  }
info
  `Data.Html.fromHtmlName('ROOT')` is the empty name `''`.

  Otherwise, `Data.Html.fromHtmlName(htmlName)` is generated as follows:
  Each occurrence of the word `DOLLAR` is replaced by the dollar sign `$` and each hyphen `-` is replaced by a dot `.`.

  For example,

      ..........................

comment
  UPDATE/CHANGE THIS!!! The `$` conversion is obsolete!!!

  In the implementation with used `"\u0024"` instead of `'$'` and `new RegExp ('-', 'g')` instead of `/-/g` because the unit compilation could not compile the regular expression literal correctly.
---
unit
  function
name
  Data.Html.htmlNameCompare
type
  Type.lambda ([HTML_NAME, HTML_NAME, Type.finite ([-1, 0, 1])])
value
  function (n1) {
    return function (n2) {
      return Str.compare (Str.toLowerCase (n1)) (Str.toLowerCase (n2));
    }
  }
info
  .........
---

---
// HTML element creation
---
unit
  doc
name
  Data.Html
header
  HTML creators
---
---
unit
  type
name
  Data.Html.HTML_DOC
value
  Type.synonym (STRING)
---
unit
  function
name
  Data.Html.htmlDoc
type
  Type.lambda ([RECORD, HTML, HTML_DOC])
value
  function (parameter) {
    return function (bodyContent) {

      // Normalize the `parameter` record
      var title       = parameter.title       || '';
      var script      = parameter.script      || '';
      var scriptLinks = parameter.scriptLinks || [];       // type `Type.list(URL)`; later type `HTML`
      var css         = parameter.css         || '';
      var cssLinks    = parameter.cssLinks    || [];       // of type `Type.list(URL)`; later type `HTML`

      // turn the parameter values into HTML
      if (title) {
        title = '<title>' + title + '</title>\n';
      }
      if (css) {
        css = '<style type="text/css">\n' + Str.indent(2)(css) + '\n</style>\n';
      }
      if (script) {
        script = "<" + 'script' + ">" + "\n" + script + "\n" + "<" + '/' + 'script' + ">" + "\n";
      }
      if (scriptLinks.length > 0) {
        for (var i = 0; i < scriptLinks.length; i++) {
          scriptLinks[i] = "<" + "script src=\"" + scriptLinks[i] + "\"" + ">" + "<" + "/" + 'script' + ">\n";
        }
      }
      scriptLinks = scriptLinks.join ("");                // now, `scriptLinks` is of type `HTML`
      if (cssLinks.length > 0) {
        for (var i = 0; i < cssLinks.length; i++) {
          cssLinks[i] = '<link rel="stylesheet" type="text/css" href="' + cssLinks[i] + '">\n'
        }
      }
      cssLinks = cssLinks.join ("\n");                    // now. `cssLinks` is of type `HTML`

      // the resulting HTML document
      return ( '<!' + 'DOCTYPE html>\n'
             + '<' + 'html>\n'
             + '<head>\n'
             + '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n'
             + title
             + css
             + cssLinks
             + script
             + scriptLinks
             + '</head>\n'
             + '<body>\n'
             + bodyContent + '\n'
             + '</body>\n'
             + '</html>\n' );

    }
  }
info
  `Data.Html.htmlDoc(parameter)(bodyContent)` returns a HTML5 document with the `parameter` in the `<head>` part and `bodyContent` inserted in the `<body>` part.

  The `parameter` record has the signature

      { title       : STRING,
        css         : $Css,
        cssLinks    : $list ($Url),
        script      : $EcmaScript,
        scriptLinks : $list ($Url) }

  Each property is optional and if `parameter` contains other properties than the mentioned ones, they are ignored.

  A general example is this:

      > var paramRec = {title: '..title..', css: '/* ..CSS.. */', cssLinks: ['one/style/sheet.css'], script: '// .. script ..', scriptLinks: ['script1.js','path/to/script2.js']}
      > Data.Html.htmlDoc (paramRec) ('<!-- body content -->')
      > display(_)
      ╭──────────────────────────────────────────────────────────────────────╮
      │...                                                                   │
      │...                                                                   │
      │...                                                                   │
      ╰──────────────────────────────────────────────────────────────────────╯
      undefined

  Note, that the `script` is inserted before `scriptLinks` in the `<head>` part.
  If you want some script to be evaluated after the `scriptLinks`, add them to the `bodyContent` part.

  Another example,

      > Data.Html.htmlDoc ({}) ("<h1> Hello World </h1>")
      > display (_)
      ╭──────────────────────────────────────────────────────────────────────╮
      │...                                                                   │
      │...                                                                   │
      │...                                                                   │
      ╰──────────────────────────────────────────────────────────────────────╯
      undefined

  And another example

      > var parameter = {
          title: "Small example",
          scriptLinks: ["http://code.jquery.com/jquery-1.11.2.js", "local-file.js"],
          css: "body { background-color:yellow }"
        }
      > Data.Html.htmlDoc (parameter) ("<h1> Hello there! </h1>")
      > display (_)
      ╭──────────────────────────────────────────────────────────────────────╮
      │...                                                                   │
      │...                                                                   │
      │...                                                                   │
      ╰──────────────────────────────────────────────────────────────────────╯
      undefined

---
---
// end Data.Html
---










---
// Data.CSS
---
---
unit
  doc
name
  Data
header
  Cascading Style Sheets (CSS)
---
---
unit
  type
name
  Data.CSS
value
  STRING // DUMMY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
---
---
// end Data.CSS
---









---
// Data.Markdown
---
---
unit
  doc
name
  Data
header
  Markdown
info
  Note, that the Markdown-to-Html converter `Data.Markdown.toHtml` uses the weaker <a href="https://github.com/evilstreak/markdown-js">markdown-js</a> package.
  The `Pandoc.markdownToHtml` converter from the `pandoc` tofu is more powerful.
---
---
unit
  type
name
  Data.MARKDOWN
value
  Type.synonym (STRING)
---
---
unit
  struct
name
  Data.Markdown
---
---
unit
  function
name
  Data.Markdown.toHtml
type
  Type.fun ([Type.MARKDOWN, Data.HTML])
value
  function (md) {
    return require ('markdown') . markdown . toHTML (md);
  }
info
  `Data.Markdown.toHtml (md)` converts the markdown string `md` into HTML code.
  For example,

      > Data.Markdown.toHtml ('The number `123`, also called *onehundredtwentythree*  is a **very** easy to remember.')
      '<p>The number <code>123</code>, also called <em>onehundredtwentythree</em>  is a <strong>very</strong> easy to remember.</p>'

---
unit
  function
name
  Data.Markdown.inlineHtml
type
  Tof.fun ([Type.MARKDOWN, Data.HTML])
value
  function (md) {
    var html = Str.trim (toHtml (md));
    if (Str.startsWith (html) ('<p>') || Str.endsWith (html) ('</p>')) {
      html = html.substring (3, html.length-4);  // remove the outer `<p>...</p>`
      html = Str.trim (html);                    // remove outer white space
      return html;
    } else {
      return html;
    }
  }
info
  Usually, Markdown-to-HTML converters (like [Pandoc](http://pandoc.org) or our [`Data.Markdown.toHtml`](#Data.Markdown.toHtml) here) wrap a `<p>` tag around small document fragments. For example,

      > Data.Markdown.toHtml ('The term `12 + 34` equals _46_ or **fourty-six**.')
      '<p>The term <code>12 + 34</code> equals <em>46</em> or <strong>fourty-six</strong>.</p>'

  But this outer `<p>...</p>` element is often not wanted.
  Therefore, we have the alternative

      > Data.Markdown.inlineHtml ('The term `12 + 34` equals _46_ or **fourty-six**.')
      'The term <code>12 + 34</code> equals <em>46</em> or <strong>fourty-six</strong>.'

  that returns the same HTML, but without the outer `<p>` element.
---
---
// end Markdown
---




















---
---
unit
  doc
name
  Data
header
  **Important Data Structures for TofJs**
---
---






---
---
unit
  doc
name
  Data
header
  Identifiers and Names
info
  ...
---
---
unit
  struct
name
  Data.Name
---
---
unit
  doc
name
  Data.Name
header
  Names as Identifier Lists
info
  See also the `Global.Name` structure.
---
---
unit
  function
name
  Data.Name.fromIdentifierList
type
  Type.lambda ([Type.list (EcmaScript.IDENTIFIER), EcmaScript.NAME])
value
  function (idL) {
    return idL.join ('.');
  }
info
  ...
---
unit
  function
name
  Data.Name.toIdentifierList
type
  Type.lambda ([EcmaScript.NAME, Type.list (EcmaScript.IDENTIFIER)])
value
  function (s) {
    if (s === '') { return []; }
    else          { return s.split ("."); }
  }
info
  ...
---
unit
  function
name
  Data.Name.depth
type
  Type.lambda ([EcmaScript.NAME, INT])
value
  function (s) {
    return toIdentifierList (s) . length;
  }
info
  ...
---
unit
  function
name
  Data.Name.joinList
type
  Type.lambda ([Type.list (EcmaScript.NAME), EcmaScript.NAME])
value
  function (sL) {
    var idL = [];
    for (var i = 0; i < sL.length; i++) {
      idL = idL.concat (toIdentifierList (sL [i]));
    }
    return fromIdentifierList (idL);
  }
info
  ...
---
unit
  function
name
  Data.Name.childIdentifier
type
  Type.lambda ([EcmaScript.NAME, EcmaScript.IDENTIFIER])
value
  function (s) {
    var idL = toIdentifierList (s);
    if (idL.length > 0) {
      return idL [idL.length -1];
    } else {
      throw Error ("The empty name does not have a parent.");
    }
  }
info
  ...
---
unit
  function
name
  Data.Name.parentName
type
  Type.lambda ([EcmaScript.NAME, EcmaScript.NAME])
value
  function (s) {
    var idL = toIdentifierList (s);
    if (idL.length > 0) {
      return fromIdentifierList (idL.slice (0, idL.length-1));
    } else {
      throw Error ("The empty name does not have a parent name.");
    }
  }
info
  ...
---
---
unit
  doc
name
  Data.Name
header
  String-Identifier Conversions
---
---
unit
  function
name
  Data.Name.string2identifierList
type
  Type.lambda ([STRING, Type.list (EcmaScript.IDENTIFIER)])
value
  function (s) {
    var rex = RegExp (/[$A-Z_][$0-9A-Z_]*/i);
    var idL = [];
    var result;
    var id;
    do {
      result = rex . exec (s);
      if (result !== null) {
        id = result [0];
        idL.push (id);
        s = s.substring (result.index + id.length);
      }
    } while (result !== null);
    return idL;
  }
info
  `Data.Name.string2identifierList (s)` returns the string `s` into the list of identifiers that occur in it.
  For example,

      > Data.Name.string2identifierList ('  One Two  three  foo123  a2b  _x_y_z_  done')
      [ 'One', 'Two', 'three', 'foo123', 'a2b', '_x_y_z_', 'done' ]

      > Data.Name.string2identifierList ('x.y&^z    123.456.789  x123  , ; bla,bla,bla ')
      [ 'x', 'y', 'z', 'x123', 'bla', 'bla', 'bla' ]

---
unit
  function
name
  Data.Name.string2tokenList
type
  Type.lambda ([STRING, Type.list (STRING)])
value
  function (s) {
    var rex = RegExp (/[$0-9A-Z_]+/i);
    var idL = [];
    var result;
    var id;
    do {
      result = rex . exec (s);
      if (result !== null) {
        id = result [0];
        idL.push (id);
        s = s.substring (result.index + id.length);
      }
    } while (result !== null);
    return idL;
  }
info
  `Data.Name.string2tokenList (s)` returns the string `s` into the list of tokens that occur in it.

  By __token__ we here mean any non-empty string, made of letters (`A`, ..., `Z`, `a`, ..., `z`), digits (`0`, `1`, ..., `9`), dollars (`$`) and understrokes (`_`).

  For example,

      > Data.Name.string2tokenList ('  One Two  three  foo123  a2b  _x_y_z_  done')
      [ 'One', 'Two', 'three', 'foo123', 'a2b', '_x_y_z_', 'done' ]

      > Data.Name.string2tokenList ('x.y&^z    123.456.789  x123  , ; bla,bla,bla ')
      [ 'x', 'y', 'z', '123', '456', '789', 'x123', 'bla', 'bla', 'bla' ]

---
unit
  function
name
  Data.Name.string2name
type
  Type.lambda ([STRING, EcmaScript.NAME])
value
  function (s) {
    return string2identifierList (s) . join ('.');
  }
info
  `Data.Name.string2name (s)` turns the string `s` into a name.
  For example,

      > Data.Name.string2name ('  One Two  three  foo123  a2b  _x_y_z_  done')
      'One.Two.three.foo123.a2b._x_y_z_.done'

      > Data.Name.string2name ('x.y&^z    123.456.789  x123  , ; bla,bla,bla ')
      'x.y.z.x123.bla.bla.bla'

  Note, that

  > `s` is a name iff `Data.Name.string2name(s) === s`, for every string `s`.

  For example,

      > Data.Name.string2name ('Data.Name.string2name')
      'Data.Name.string2name'

      > Data.Name.string2name ('string2name')
      'string2name'

      > Data.Name.string2name ('')
      ''

      > Data.Name.string2name ('One.Two.three.foo123.$dollar$._x_y_z_')
      'One.Two.three.foo123.$dollar$._x_y_z_'

---
unit
  function
name
  Data.Name.string2identifier
type
  Type.lambda ([STRING, EcmaScript.IDENTIFIER])
value
  function (s) {
    var tokL = string2tokenList (s);
    if (tokL.length > 0) { var i = tokL.join ('_');
                           if ("0" <= i[0] && i[0] <= "9") { return '_' + i; }
                           else                            { return i; } }
    else                 { return '_';  }
  }
info
  `Data.Name.string2identifier (s)` turns the string `s` into an identifier.

  This conversion is done in two steps:

  1. First, `s` is converted into a list of tokens `[t_1, ..., t_n]` by means of `Data.Name.string2tokenList(s)`.

  2. The list `[t_1, ..., t_n]` of tokens is converted into an identifier `i` as follows:

        2.1 If the token list is empty (i.e. `n` is `0`), the identifier `i` is `"_"`.
        2.2 A non-empty token list is converted into the string `t_1 + '_' + ... + '_' + t_n`. If the result starts with a digit, an understroke `'_'` is also added to the front.

  For example,

      > Data.Name.string2identifier ('  One Two  three  foo123  a2b  _x_y_z_  done')
      'One_Two_three_foo123_a2b__x_y_z__done'

      > Data.Name.string2identifier ('x.y&^z    123.456.789  x123  , ; bla,bla,bla ')
      'x_y_z_123_456_789_x123_bla_bla_bla'

      > Data.Name.string2identifier (' 123 456 and 7890  ');
      '_123_456_and_7890'

---
---
unit
  doc
name
  Data.Name
header
  HTML Names
info
  We defined a __name__ according to the syntax rule of ECMAScript: it may contain the dollar sign `$` and it is case-sensitive.
  The according type of all these names is `EcmaScript.NAME`.
  But names in HTML, i.e. values for the [`id` attribute](http://www.w3schools.com/tags/att_global_id.asp), are case-insensitive and must not contain `$`.
  For that reason, we define `HTML_NAME`s as a separate type together with conversions between them

                           toHtmlName
      EcmaScript.NAME -------------------> HTML_NAME

                   fromHtmlName
      HTML_NAME -------------------> EcmaScript.NAME

---
---
unit
  type
name
  Data.Name.HTML_NAME
value
  Type.subType (STRING) (function (s) {
      var rex = /^[A-Za-z][A-Za-z0-9-]*$/;
      if (rex.test (s)) {
        return "";
      } else {
        return ( "`" + s + "` is not a non-empty string, beginning with a letter and only comprising letters, digits and hyphens.")
      }
    }
  )
info

  # UPDATE ALL THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  A __HTML name__, is a non-empty string, only made of letters (`A`,...,`Z`,`a`,...,`z`), digits (`0`,`1`,...,`9`), hyphens (`-`), underscores (`_`), and beginning with a letter.



  `Data.Name.HTML_NAME` is the type of all these HTML names.







  Examples of HTML names are:

      `"this-is-a-HTML-name"`   `"about-a-100-things"`   `"section-2-7"`

  Counterexamples are:

  * `"this is not a HTML name"` is not a HTML name, because it contains spaces
  * `"no_good_either"` is not a HTML name, because it contains underscores
  * `"1000-years"` is not a HTML name, because it does not start with a letter
  * `""` the empty string is not a HTML name.
  * `"abc*$def"` is not a HTML name, because it contains a `*` and a `$`

  Accordingly, we obtain

      > Data.Name.HTML_NAME.chi ("this-is-a-HTML-name")
      true
      > Data.Name.HTML_NAME.chi ("about-a-100-things")
      true
      > Data.Name.HTML_NAME.chi ("section-2-7")
      true
      > Data.Name.HTML_NAME.chi ("this is not a HTML name")
      false
      > Data.Name.HTML_NAME.chi ("1000-years")
      false
      > Data.Name.HTML_NAME.chi ("")
      false
      > Data.Name.HTML_NAME.chi ("abc*$def")
      false



  ....................................



  Note, that the [official HTML4 definition of ID and NAME tokens](http://www.w3.org/TR/html4/types.html#type-id) are more permissive than our `HTML_NAME` type: they must begin with a letter (`A`,...,`Z`,`a`,...,`z`) and may be followed by any number of letters, digits (`0`,...,`9`), hyphens (`-`), underscores (`_`), colons (`:`) and periods (`.`).
  [HTML5](http://www.w3.org/TR/html5/dom.html#the-id-attribute) is even more permissive and says it must start with an arbitrary character, followed by more characters, not containing space symbols.
  Our `HTML_NAME` definition is more restrictive, because it avoids problems when the names are used in other contexts, like CSS, where colons and periods have a special and different meaning.

  There is a nice stackoverflow post on the question [_What are valid values for the id attribute in HTML?_](http://stackoverflow.com/questions/70579/what-are-valid-values-for-the-id-attribute-in-html)
---
unit
  value
name
  Data.Name.rootHtmlName
type
  Data.Name.HTML_NAME
value
  '.'
info
  The __root HTML Name__ is defined as the single dot string (`"."`).

  Recall, that we defined (standard ECMAScript) names (i.e. `EcmaScript.NAME` values) as sequences of identifiers (i.e. `ECMAScript.IDENTIFIER` values) separated by dots (`.`). For example, `'One.Two.three.foo123'` is a (standard) name, made of four identifiers.
  According to this definition, the empty string `""` is a well-defined name, too.
  That makes sense, because this empty name always refers to the root of the global object, which is the global object itself.
  In other words, `Global.getValue("")` is always the global object, say `window` in any browser environment.

  However, the empty or root name `""` may be a well-defined (standard) name, but it is not a HTML name, because that always requires to commence with a letter.
  For that reason, we need to have a distinguished HTML name that corresponds to the empty standard name.
  And we choose `"."` to serve that purpose.
---
unit
  function
name
  Data.Name.toHtmlName
type
  Type.lambda ([EcmaScript.NAME, HTML_NAME])
value
  function (s) {
    if (s === '') { return rootHtmlName; }
    else          { return s; }
  }
info
  ...
---
unit
  function
name
  Data.Name.fromHtmlName
type
  Type.lambda ([HTML_NAME, EcmaScript.NAME])
value
  function (h) {
    if (h === rootHtmlName) { return ''; }
    else                    { return h;  }
  }
info
  ....
---
// end Data.Name
---





---
// Data.Moral
---
unit
  doc
name
  Data
header
  Moral
---
---
unit
  type
name
  Data.MORAL
value
  Type.or (Type.model ({good: ANYTHING})) (Type.model ({bad: STRING}))
info
  A `Data.MORAL` value is a one-property record, namely either of the signature `{good: ANYTHING}` or `{bad: STRING}`.

  The purpose of this data type is it to provide a proper value alternative to an disruptive error message.
---
unit
  struct
name
  Data.Moral
---
unit
  function
name
  Data.Moral.type
type
  Type.lambda ([TYPE, TYPE])
value
  function (t) {
    return Type.fromRecord ({
      expression:
        'Data.Moral.type (' + ( Type.name(t) || Type.expression(t) ) + ')',
      complain:
        function (x) {
          if (typeof x === 'object') {
            if (x === null) {
              return ("The given value is `null`.");
            } else {
              var keyL = Rec.keys (x);
              if (keyL.length !== 1) {
                return ("The given object has not only one, but `" + keyL.length + "` properties.");
              } else {
                if (keyL[0] === 'good') {
                  if (chi (t) (x.good)) {
                    return '';
                  } else {
                    return ( "The value has the form `{good: x}`, but the value `x` is `" + Any.ellipsis(x.good) + "` and is not of the required type `"
                           + literal(t) + "`:\n" + Any.ellipsis(x.good) );
                  }
                } else if (keyL[0] === 'bad') {
                  if (typeof x.bad === 'string') {
                    return '';
                  } else {
                    return ("The `bad` value of the given object is not a string, but a `" + (typeof x.bad) + "` value.");
                  }
                } else {
                  return ("The given one-property object has the undefined property key `" + keyL[0] + "`.");
                }
              }
            }
          } else {
            return ("The given value is no record, at all.");
          }
        },
      cardinality:
        function () { return null; },
      members:
        function () { return null; },
      supremum:
        RECORD
    })
  }
info
  `Data.Moral.type(t)` is the __moral type__ of (the given type) `t`, where each member has of of two forms:

  * `{good: x}` with `x` being a value of type `t`, or
  * `{bad: s}` with `s` being a string.

  .........
---
unit
  function
name
  Data.Moral.good
type
  Type.lambda ([Type.T0, Data.Moral.type (Type.T0)])
value
  function (x) {
    return Rec.create ({good: x})
  }
info
  `Data.Moral.good(x)` wraps the value `x` (of arbitrary type `T0`) into a moral value `{good: x}`.
---
unit
  function
name
  Data.Moral.bad
type
  Type.lambda ([Type.or (NULL) (STRING), Data.Moral.type (Type.T0)])
value
  function (s) {
    return Rec.create ({bad: s});
  }
info
  `Data.Moral.bad(s)` wraps the string message `s` into a moral value `{bad: s}`.
---
unit
  function
name
  Data.Moral.isGood
type
  Type.lambda ([Data.Moral.type (Type.T0), BOOLEAN])
value
  function (x) {
    return Rec.isKey (x) ('good');
  }
info
  `Data.Moral.isGood(x)` returns `true`, if the moral value `x` is good, and `false` otherwise.
---
unit
  function
name
  Data.Moral.isBad
type
  Type.lambda ([Data.Moral.type (Type.T0), BOOLEAN])
value
  function (x) {
    return Rec.isKey (x) ('bad');
  }
info
  `Data.Moral.isBad(x)` returns `true`, if the moral value `x` is bad, and `false` otherwise.
---
unit
  function
name
  Data.Moral.goodValue
type
  Type.lambda ([Data.Moral.type (Type.T0), Type.T0])
value
  function (x) {
    if (isGood (x)) { return Rec.of (x) ('good'); }
    else            { throw Error ('The argument is not a good moral value.'); }
  }
info
  ...
---
unit
  function
name
  Data.Moral.badValue
type
  Type.lambda ([Data.Moral.type (Type.T0), STRING])
value
  function (x) {
    if (isBad (x)) { return Rec.of (x) ('bad'); }
    else           { throw Error ('The argument is not a bad moral value.'); }
  }
info
  ...
---
// end Data.Moral
---










---
// Data.LinOrd
---
---
unit
  doc
name
  Data
header
  Linear Order
comment
  Change this `Data.LinOrd` structure into a parameterized data structure, generated by a comparator function `T0 --> T0 --> Type.finite ([-1, 0, 1])`!!!
---
unit
  struct
name
  Data.LinOrd
---
unit
  function
name
  Data.LinOrd.equality
value
  function (compare) {
    function eq (x) {
      return function (y) {
        switch (compare (x) (y)) {
          case -1: return false;
          case  0: return true;
          case  1: return false;
        }
      }
    }
  }
info
  `Data.LinOrd.equality(compare)` returns the equality function induced by the `compare` function.
---
// end Data.LinOrd
---












------------------------------------------------------------------------------------------------------
// Data.Flags
------------------------------------------------------------------------------------------------------
---
unit
  doc
name
  Data
header
  Flags and general types and operations on flags
---
unit
  struct
name
  Data.Flags
---
unit
  type
name
  Data.Flags.FLAG_SCHEMA
value
  Type.synonym (Type.record (Type.nonEmptyList (EcmaScript.IDENTIFIER)))
info
  A __flag schema__ is an identifier list record, i.e. a record of the form

      { k_1: [i_1_1, ..., i_1_n1],
        k_2: [i_2_1, ..., i_2_n2],
        ...
        k_m: [i_m_1, ..., i_m_nm] }

  where each of the `i_1_1`, ..., `i_m_nm` is an identifier and each of the value lists are non-empty (i.e. the `n1`, ..., `nm` are all positive integers).

  For example, a flag schema is given by

      { color    : ['red', 'green', 'blue']    ,
        position : ['left', 'right', 'middle'] ,
        extend   : ['normal, 'big', 'small']   ,
        layout   : ['inline', 'box']           }

  so that

      ................................

---
unit
  type
name
  Data.Flags.FLAG_STRING
value
  Type.subType (STRING) ({function (s) {
    try {
      flagString2idList (s);
      return '';
    } catch (e) {
      return e;
    }
  }})
info
  A __flag string__ is a string, only made of identifiers, separated by white space characters (`" "`, `"\n"`, `"\t"`, etc)

  For example,

      > Type.chi (Data.Flags.FLAG_STRING) ('One two three')
      .......

  ..........

---
unit
  type
name
  Data.Flags.FLAG_RECORD
value
  Type.synonym (Type.record (EcmaScript.IDENTIFIER))
info
  A __flag record__ is an identifier record. For example,

      { color    : 'green'  ,
        position : 'left'   ,
        size     : 'small'  ,
        layout   : 'inline' }

  is a flag record.

  For example,

      ................

---
unit
  function
name
  Data.Flags.flagSchemaSignature
type
  Type.fun ([Data.Flags.FLAG_SCHEMA, Type.SIGNATURE])
value
  function (flagSchema) {
    return Rec.map (Type.finite) (flagSchema);
  }
info
  `Dat.Flags.flagSchemaSignature ({k_1: iL_1, ..., k_n: iL_n})` converts the given Flag Schema into the Type Signature
  `{k_1: Type.finite (iL_1), ..., k_n: Type.finite (iL_n)}`.

  For example,

      .....

---
unit
  function
name
  Data.Flags.flagStringType
type
  Type.fun ([Data.Flags.FLAG_SCHEMA, Type.sub (STRING)])
value
  function (flagSchema) {
    return Type.subType (STRING) (function (s) {
      return ''; // DUMMY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

      // `s` needs to be checked if it contains the flags from `flagSchema`, only!!!!!!!!!!!!!!!!!!!!!!!!!!

    });
  }
info
  ...
comment
  Implement that!!!!!!!!!!!!!!!!1
---
unit
  function
name
  Data.Flags.flagRecordType
type
  Type.fun ([Data.Flags.FLAG_SCHEMA, Type.sub (RECORD)])
value
  function (flagSchema) {
    return Type.model (flagSchemaSignature (flagSchema));
  }
info
  ...
---
unit
  function
name
  Data.Flags.flagString2idList
type
  Type.fun ([Data.Flags.FLAG_STRING, Type.list (EcmaSript.ID)])
value
  function (flagString) {
    // 1. turn `flagString` into a list of non-empty words
    var wordList = flagString . trim () . split (/\s+/);
    if (wordList.length === 1 && wordList[0] === '') { wordList = []; } // clean up in case `wordList` is ['']
    // 2. make sure, each word is an ECMAScript identifier
    for (var i = 0; i < wordList.length ; i++) {
      if (! Type.chi (EcmaScript.IDENTIFIER) (wordList [i])) {
        throw Error ("The word `" + wordList[i] + "` in the given string is not a proper identifier.");
      }
    }
    return wordList;
  }
info
  ...

  For example,

      > Data.Flags.flagString2idList  (' One two three  \n four five six ')
      [ 'One', 'two', 'three', 'four', 'five', 'six' ]

---
unit
  function
name
  Data.Flags.flagString2flagRecord
type
  type.fun ([Data.Flags.FLAG_SCHEMA, Data.Flags.FLAG_STRING, Data.Flags.FLAG_RECORD])
value
  function (flagSchema) {
    return function (flagString) {
      var rec = {};
      var valueL = flagString2idList (flagString);
      for (var i = 0; i < valueL.length; i++) {
        var found = false;
        for (var k in flagSchema) {
          for (var j = 0; j < flagSchema[k].length; j++) {
            if (valueL[i] === flagSchema[k][j]) {
              if (k in rec) {
                throw Error ("There are two `" + k + "`-values in the given flag string, anmely `" + rec[k] + "` and `" + valueL[i] + "`.");
              } else {
                found = true;
                rec[k] = valueL[i];
              }
            }
          }
        }
        if (! found) {
          throw Error ("`" + valueL[i] + "` is no value of the given flag schema.")
        }
      }
      return Rec.create (rec);
    }
  }
info
  Data.Flags.flagString2flagRecord(flagSchema)(flagString) tries to return a $FlagRecord, which is a model of the given flagSchema and so that its values are the values written in flagString.

  For example,

      > var flagSchema = {color: ['red', 'blue', 'yellow'], size: ['big', 'small', 'medium'], shape: ['circle', 'square', 'triangle']}
      undefined

      > Data.Flags.flagString2flagRecord (flagSchema) (" red  triangle ")
      { color: 'red', shape: 'triangle' }

      > Data.Flags.flagString2flagRecord (flagSchema) (" circle  triangle ")
      Error: `Data.Flags.flagString2flagRecord(flagSchema)(flagString)` error, there are two `shape` values in `flagString`, namely `circle` and `triangle`.

      > Data.Flags.flagString2flagRecord (flagSchema) (" ")
      {}

      > Data.Flags.flagString2flagRecord (flagSchema) (" red 123.456 ")
      Error: The word `123.456` in the given string is not an identifier.

---
unit
  function
name
  Data.Flags.defaultFlagSchemaRecord
type
  Type.fun ([Data.Flags.FLAG_SCHEMA, Data.Flags.FLAG_RECORD])
value
  function (flagSchema) {
    return Rec.map (List.first) (flagSchema);
  }
info
  `Data.Flags.defaultFlagSchemaRecord (x)` returns the flag record of `x` which is made of each first value in the lists of `x`. In other words,

      Data.Flags.defaultFlagSchemaRecord ({k_1: [i_1_1, ...], ..., k_n: [i_n_1, ...]})

  returns

      {k_1: i_1_1, ..., k_n: i_n_1}

  For example,

      > Data.Flags.defaultFlagSchemaRecord ({color: ['red', 'blue', 'yellow'], size: ['big', 'small', 'medium'], shape: ['circle', 'square', 'triangle']}
      {color: 'red', size: 'big', shape: 'circle'}

---
unit
  function
name
  Data.Flags.flagSchemaUnion
type
  Type.fun ([Type.list (Data.Flags.FLAG_SCHEMA), Data.Flags.FLAG_SCHEMA])
value
  function (flagSchemaL) {
    var flagSchema = {};
    for (var i = 0; i < flagSchemaL.length; i++) {
      var fs = flagSchemaL [i];
      for (var k in fs) {
        if (k in flagSchema) {
          flagSchema[k] = List.uniq (List.concat ([flagSchema[k], fs[k]]));
        } else {
          flagSchema[k] = fs[k];
        }
      }
    }
    return Rec.create (flagSchema);
  }
info
  `Data.Flags.flagSchemaUnion ([fs_1, ..., fs_n])`` returns the __flag schema union__ of the single flag schemas `fs_1`, ..., `fs_n`.
  For example,

      > var x1 = {color: ['red', 'green'], size: ['big']}
      undefined

      > var x2 = {color: ['yellow'], shape: ['circle', 'square']}
      undefined

      > Data.Flags.flagSchemaUnion ([x1, x2])
      { color: [ 'red', 'green', 'yellow' ], size: [ 'big' ], shape: [ 'circle', 'square' ] }

------------------------------------------------------------------------------------------------------
// end Data.Flags
------------------------------------------------------------------------------------------------------






















---
---
unit
  doc
name
  Data
header
  **Numeric data structures**
---
---






---
---
// Data.NAT
---
---
unit
  doc
name
  Data
header
  Small Natural Numbers
---
---
unit
  type
name
  Data.NAT
value
  Type.subType (INT) (function (i) {
    if (i < 0) { return ("The given number is negative."); }
    else       { return ""; }
  })
info
  A [__natural number__](https://en.wikipedia.org/wiki/Natural_number) is one of the numbers `0`, `1`, `2`, `3`, `4`, ....

  A __small natural number__ is any non-negative small/safe integer (i.e. `INT` value), i.e. any of the integers between `0` and `2^53-1`, inclusively, where `2^53-1` is `900719925474099`, also given by `Int.maxInt` or the native ES6 value `Number.MAX_SAFE_INTEGER`.

  `Data.NAT` is the type of all small natural numbers.

  For example,

      ......

---
unit
  struct
name
  Data.Nat
---
unit
  function
name
  Data.Nat.compare
type
  Type.lambda ([NAT, NAT, Type.finite ([-1, 0, 1])])
value
  function (n1) {
    return function (n2) {
      if      (n1 < n2) { return -1; }
      else if (n1 > n2) { return 1; }
      else              { return 0; }
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.eq
type
  Type.lambda ([NAT, NAT, BOOLEAN])
value
  function (n1) {
    return function (n2) {
      return (n1 === n2);
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.le
type
  Type.lambda ([NAT, NAT, BOOLEAN])
value
  function (n1) {
    return function (n2) {
      return (n1 <= n2);
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.ge
type
  Type.lambda ([NAT, NAT, BOOLEAN])
value
  function (n1) {
    return function (n2) {
      return (n1 >= n2);
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.lower
type
  Type.lambda ([NAT, NAT, BOOLEAN])
value
  function (n1) {
    return function (n2) {
      return (n1 < n2);
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.greater
type
  Type.lambda ([NAT, NAT, BOOLEAN])
value
  function (n1) {
    return function (n2) {
      return (n1 > n2);
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.min
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      if (n1 < n2) { return n1; }
      else         { return n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.max
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      if (n1 > n2) { return n1; }
      else         { return n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.plus
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      return n1 + n2
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.difference
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      if (n1 > n2) { return n1 - n2; }
      else         { return n2 - n1; }
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.times
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      return n1 * n2;
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.div
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      if (n2 === 0) {
        throw Error ("Division by zero.");
      } else {
        return Math.floor (n1 / n2);
      }
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.mod
type
  Type.lambda ([NAT, NAT, NAT])
value
  function (n1) {
    return function (n2) {
      if (n2 === 0) {
        throw Error ("Division by zero.");
      } else {
        return ((n1 % n2 + n2) % n2);
      }
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.quot
type
  Type.lambda ([NAT, NAT, Type.tuple ([NAT, NAT])])
value
  function (n1) {
    return function (n2) {
      return [Math.floor (n1 / n2), (n1 % n2 + n2) % n2];
    }
  }
info
  ...
---
unit
  function
name
  Data.Nat.gcd
type
  Type.lambda ([NAT, NAT, BOOLEAN])
value
  Int.gcd;
info
  ...
---
unit
  function
name
  Data.Nat.power
type
  Type.lambda ([NAT, NAT, NAT])
value
  Int.power
info
  ...
---
unit
  function
name
  Data.Nat.sum
type
  Type.lambda ([Type.list (NAT), NAT])
value
  function (nL) {
    return List.reduce (plus) (0) (nL);
  }
info
  ...
---
unit
  function
name
  Data.Nat.product
type
  Type.lambda ([Type.list (NAT), NAT])
value
  function (nL) {
    return List.reduce (times) (1) (nL);
  }
info
  ...
---
---
// end Data.Nat
---







---
---
// Data.NULL_CARDINAL and Data.NullCardinal
---
---
unit
  doc
name
  Data
header
  Nullified Small Cardinal Numbers
---
---
unit
  type
name
  Data.NULL_CARDINAL
value
  Type.union ([NULL, NAT, Type.single (Infinity)])
---
unit
  struct
name
  Data.NullCardinal
---
unit
  function
name
  Data.NullCardinal.compare
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, Type.finite ([null, -1, 0, 1])])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else if (n1 < n2) { return -1; }
      else if (n1 > n2) { return  1; }
      else              { return  0; }
    }
  }
info
  `Data.NullCardinal.compare (n1) (n2)` returns

  * `null`, if `n1` or `n2` or both are `null`,
  * `-1`, if `n1` is smaller than `n2`,
  * `1`, if `n1` is greater than `n2`,
  * `0`, if `n1` is equal to `n2`

  For example,

      > Data.NullCardinal.compare (5) (77)
      -1

      > Data.NullCardinal.compare (Infinity) (Infinity)
      0

      > Data.NullCardinal.compare (Infinity) (12345)
      1

      > Data.NullCardinal.compare (null) (123)
      null

---
unit
  function
name
  Data.NullCardinal.eq
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, Type.nullify (BOOLEAN)])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return Object.is (n1, n2); }
    }
  }
info
  `Data.NullCardinal.eq (n1) (n2)` returns

  * `null`, if one or both of `n1` or `n2` is `null`,
  * `true`, if `n1` and `n2` are equal and other than `null`
  * `false`, if neither `n1` nor `n2` is `null` and both are different numbers.

  For example,

      > Data.NullCardinal.eq (123) (123)
      true

      > Data.NullCardinal.eq (123) (321)
      false

      > Data.NullCardinal.eq (123) (null)
      null

      > Data.NullCardinal.eq (null) (null)
      null

---
unit
  function
name
  Data.NullCardinal.le
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, Type.nullify (BOOLEAN)])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return n1 <= n2; }
    }
  }
info
  `Data.NullCardinal.le (n1) (n2)`, reading `n1` **lower-or-equal** `n2`,returns

  * `null`, if at least one of `n1` and `n2` is `null`
  * `true`, if neither `n1` nor `n2` is `null` and `n1` lower or equal `n2`,
  * `false`, if neither `n1` nor `n2` is `null` and `n1` is bigger than `n2`.

  For example,

      > Data.NullCardinal.le (123) (Infinity)
      true

      > Data.NullCardinal.le (123) (null)
      null

      > Data.NullCardinal.le (Infinity) (Infinity)
      true

---
unit
  function
name
  Data.NullCardinal.ge
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, Type.nullify (BOOLEAN)])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return n1 >= n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.lower
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, Type.nullify (BOOLEAN)])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return n1 < n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.greater
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, Type.nullify (BOOLEAN)])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return n1 > n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.min
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return Math.min (n1, n2); }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.max
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return Math.max (n1, n2); }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.plus
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return n1 + n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.difference
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else if (n1 <= n2)              { return n2 - n1; }
      else                            { return n1 - n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.times
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else                            { return n1 * n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.div
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else if (n2 === 0)              { throw Error ("Division by zero."); }
      else if (n2 === Infinity)       { throw Error ("Division by Infinity."); }
      else                            { return Math.floor (n1 / n2); }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.mod
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else if (n2 === 0)              { throw Error ("Division by zero."); }
      else if (n2 === Infinity)       { throw Error ("Division by Infinity."); }
      else                            { return (n1 % n2 + n2) % n2; }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.power
type
  Type.lambda ([NULL_CARDINAL, NULL_CARDINAL, NULL_CARDINAL])
value
  function (n1) {
    return function (n2) {
      if (n1 === null || n2 === null) { return null; }
      else if (n1 === 0 && n2 === 0)  { return 1; }
      else if (n1 === 0)              { return 0; }
      else if (n2 === 0)              { return 1; }
      else                            { return Math.pow (n1, n2); }
    }
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.sum
type
  Type.lambda ([Type.list (NULL_CARDINAL), NULL_CARDINAL])
value
  function (nL) {
    return List.reduce (plus) (0) (nL);
  }
info
  ...
---
unit
  function
name
  Data.NullCardinal.product
type
  Type.lambda ([Type.list (NULL_CARDINAL), NULL_CARDINAL])
value
  function (nL) {
    return List.reduce (times) (1) (nL);
  }
---
---
// end Data.SmallNullCardinal
---
---













---
---
// ////////////////////////////////////////////////////////////////////////////////////////////////
---
---
unit
  doc
name
  Data
header
  **Text formatting and printing**
info
  ...
---
---
// ////////////////////////////////////////////////////////////////////////////////////////////////
---
---






---
---
// Data.Pretty
---
---
unit
  doc
name
  Data
header
  Pretty Printer
---
---
unit
  struct
name
  Data.Pretty
---
---
unit
  doc
name
  Data.Pretty
header
  Representational string display of values
---
---
unit
  function
name
  Data.Pretty.block
type
  Type.lambda ([ANYTHING, EcmaScript.EXPRESSION])
value
  function (x) {
    throw Error ("...........................Data.Pretty.block(x)...............................")
  }
info
  ....
---
unit
  function
name
  Data.Pretty.inline
type
  Type.lambda ([ANYTHING, EcmaScript.EXPRESSION])
value
  function (x) {
    throw Error ("...........................Data.Pretty.inline(x)...............................")
  }
info
  ....
---
---
unit
  doc
name
  Data.Pretty
header
  Non-representational string display of values
---
---
unit
  function
name
  Data.Pretty.ellipsis
type
  Type.lambda ([NAT, ANYTHING, STRING])
value
  function (n) {
    return function (x) {
      throw Error ("..................Data.Pretty.ellipsis(x)......................................")
    }
  }
info
  ....
---
unit
  function
name
  Data.Pretty.maxHundred
type
  Type.lambda ([ANYTHING, STRING])
value
  function (x) {
    return ellipsis (100) (x);
  }
info
  ....
---
unit
  value variable
name
  Data.Pretty.endOfLine
type
  CHAR
value
  "\u21B5"
info
  The end-of-line character &#8629; is the [Downward Arrow with Corner Leftwards](http://unicode-table.com/en/21B5/) in the Unicode Character Table. Its Unicode number is `U+21B5` (thus it is `"\u21B5"` in JavaScript), its HTML code is `&#8629`, the entity is `&crarr;`.
---
unit
  function
name
  Data.Pretty.stringBox
type
  Type.lambda ([STRING, TextBox.BOX])
value
  function (s) {
    return TextBox.create ({border: 'rounded'}) (s.split ('\n') . join (endOfLine + '\n') . split ('\n'));
  }
info
  ...

  For example,

      > Data.Pretty.stringBox ("One Two")
      [ '╭───────╮',
        '│One Two│',
        '╰───────╯' ]

      > Data.Pretty.stringBox ("One Two\nThree Four Five\n  Six.")
      [ '╭────────────────╮',
        '│One Two↵        │',
        '│Three Four Five↵│',
        '│  Six.          │',
        '╰────────────────╯' ]

---
---
unit
  doc
name
  Data.Pretty
header
  Auxiliary functions
---
---
unit
  function
name
  Data.Pretty.oneTabLine
value
  function (pairList) {
    var line = '';
    for (var i = 0; i < pairList.length; i++) {
      var n = pairList[i][0]; // of type `INT` for the column number
      var s = pairList[i][1]; // of type `STRING`
      if (n < line.length) {
        throw Error ("The column number " + n + " is too low, the string in this line is already longer at that point.");
      } else {
        line += Str.repeat (' ') (n - line.length);
        line += s;
      }
    }
    return line;
  }
type
  Type.lambda ([Type.freqList ([[INT, STRING, '*']]), STRING])
info
  `Data.Pretty.oneTabLine ([[n_1, s_1], ..., [n_k, s_k]])` returns a string, where string `s_1` begins at position `n_1`, string `s_2` begins at position `n_2`, ...., and string `s_k` begins at position `n_k`.
  For example,

      > Data.Pretty.oneTabLine ([[0, 'One'], [10, 'Two'], [20, 'Three'], [30, 'Four']])
      'One       Two       Three     Four'

  If any of the strings exceeds the subsequent position, and error is thrown. For example,

      > Data.Pretty.oneTabLine ([[0, 'One'], [10, 'This string is too long.'], [20, 'Three'], [30, 'Four']])
      Error: The column number 20 is too low, the string in this line is already longer at that point.
---
---
---
// end Data.Pretty
---
---






---
---
// Data.TextBox
---
---
unit
  doc
name
  Data
header
  Text Boxes and Text Box Grids
info
  ....
---
---
unit
  struct
name
  Data.TextBox
info
  ....
comment
  Improve the box layout by the use of [box symbols](http://unicode-table.com/en/search/?q=box).
  For example,

      > console.log("\u250F\u2501\u2513\n\u2503 \u2503\n\u2517\u2501\u251b")
      ┏━┓
      ┃ ┃
      ┗━┛
      undefined

  # Boxing characters

  [Boxing characters](http://unicode-table.com/en/search/?q=box) in Unicode and HTML

  ## Thick lines

  Character   Unicode   HTML
  ---------   --------  ---------
  &#9473;     `U+2501`  `&#9473;`
  &#9475;     `U+2503`  `&#9475;`
  &#9487;     `U+250F`  `&#9487;`
  &#9491;     `U+2513`  `&#9491;`
  &#9495;     `U+2517`  `&#9495;`
  &#9499;     `U+251B`  `&#9499;`
  &#9523;     `U+2533`  `&#9523;`
  &#9531;     `U+253B`  `&#9531;`
  &#9507;     `U+2523`  `&#9507;`
  &#9515;     `U+252B`  `&#9515;`
  &#9547;     `U+254B`  `&#9547;`

  ## Double lines

  Character   Unicode   HTML
  ---------   --------  ---------
  &#9552;     `U+2550`  `&#9552;`
  &#9553;     `U+2551`  `&#9553;`
  &#9556;     `U+2554`  `&#9556;`
  &#9559;     `U+2557`  `&#9559;`
  &#9562;     `U+255A`  `&#9562;`
  &#9565;     `U+255D`  `&#9565;`
  &#9574;     `U+2566`  `&#9574;`
  &#9577;     `U+2569`  `&#9577;`
  &#9568;     `U+2560`  `&#9565;`
  &#9571;     `U+2563`  `&#9571;`
  &#9580;     `U+256C`  `&#9580;`

  ## Thin lines

  Character   Unicode   HTML
  ---------   --------  ---------
  &#9472;     `U+2500`  `&#9472;`
  &#9474;     `U+2502`  `&#9474;`
  &#9484;     `U+250C`  `&#9484;`
  &#9488;     `U+2510`  `&#9488;`
  &#9492;     `U+2514`  `&#9492;`
  &#9496;     `U+2518`  `&#9496;`
  &#9516;     `U+252C`  `&#9516;`
  &#9524;     `U+2534`  `&#9524;`
  &#9500;     `U+251C`  `&#9500;`
  &#9508;     `U+2524`  `&#9508;`
  &#9532;     `U+253C`  `&#9532;`

  ## Arc corners

  Character   Unicode   HTML
  ---------   --------  ---------
  &#9581;     `U+256D`  `&#9581;`
  &#9582;     `U+256E`  `&#9582;`
  &#9584;     `U+2570`  `&#9584;`
  &#9583;     `U+256F`  `&#9583;`

  ## Other symbols

  Unicode   HTML       Name                      JavaScript
  --------  ---------  -----------------------   --------------
  `U+000A`  `&#10;`    New Line                  `"\n"`
  `U+0009`  `&#9;`     Horizontal Tabulation     `"\t"`
  `U+000B`  `&#11;`    Vertical Tabulation

---
---
unit
  type
name
  Data.TextBox.BOX
value
  Type.subType (Type.list (STRING)) (function (sL) {
    if (sL.length === 0) {
      return '';
    } else {
      var width = sL[0].length;
      for (var i = 1; i < sL.length; i++) {
        if (sL[i].length !== width) {
          return ("The " + i + "-th string has length `" + sL[i].length + "` and that is different from the length `" +
            width + "` of the previous strings.");
        }
        var charCodeL = Str.toCharCodeList (sL[i]);
        for (var j = 0; j < width; j++) {
          if (charCodeL [j] < 32) {
            return ("The " + i + "-th string at the " + j + "-th position is a control character (character code " + charCodeL[j] + ").");
          }
        }
      }
      return '';
    }
  })
info
  ...

  For example,

    > Type.complain (Data.TextBox.BOX) (['one'])
    ''

    > Type.complain (Data.TextBox.BOX) (['one', 'two'])
    ''

    > Type.complain (Data.TextBox.BOX) (['one', 'two', 'three'])
    'Complain of the given type:\n`["one", "two", "three"]` does not satisfy the additional condition: The 2-th string has length `5` and that is different from the length `3` of the previous strings.'
---
unit
  function
name
  Data.TextBox.string2box
type
  Type.lambda ([STRING, BOX])
value
  function (s) {
    var strL = s.split ('\n');
    try {
      var box = create ({}) (s);
    } catch (e) {
      throw Error ("Cannot convert the string to a box: " + e);
    }
    return box;
  }
info
  ....
---
unit
  function
name
  Data.TextBox.box2string
type
  Type.lambda ([BOX, STRING])
value
  function (box) {
    return box.join ('\n');
  }
info
  `Data.TextBox.box2string (box)` converts the given text `box` into a string.
  More precisely, a box `[STRING_1, ..., STRING_n]` is converted into the string `STRING_1 + .... + STRING_n`.

  For example,

       > Data.TextBox.box2string (['One  ', 'Two  ', 'Three'])
       'One  \nTwo  \nThree'

---
unit
  function
name
  Data.TextBox.width
type
  Type.lambda ([Type.list (STRING), NAT])
value
  function (box) {
    return Int.maximum (List.map (Str.length) (box));
  }
info
  `Data.TextBox.width ([s_1, ..., s_n])` returns the __width__ of the Text Box `[s_1, ..., s_n]`, which is defined as `Int.maximum ([Str.length (s_1), ..., Str.legnth (s_n)])`.

  For example,

      > Data.TextBox.width (['one', 'two', 'three'])
      5

---
unit
  function
name
  Data.TextBox.height
type
  Type.lambda ([BOX, NAT])
value
  function (box) {
    return box.length;
  }
info
  `Data.TextBox.height ([s_1, ..., s_n])` returns the __height__ of the Text Box `[s_1, ..., s_n]`, which is defined as `n`.

  For example,

      > Data.TextBox.height (['one', 'two', 'three'])
      3

---
unit
  function
name
  Data.TextBox.indentation
type
  Type.lambda ([BOX, NAT])
value
  function (box) {
    function stringIndentation (s) {
      var i = 0;
      for (var j = 0; j < s.length; j++) {
        if (Str.charAt (s) (j) === ' ') { i++; }
        else                            { return i; }
      }
      return i;
    }
    return Int.minimum (List.map (stringIndentation) (box));
  }
info
  By the indentation of a string `s` we mean the number of spaces at the beginning of `s`.
  For example, `'Hello'` has the indentation `0` and `'  Hello'` has the indentation `2`.

  By the indentation of a box `[s_1, ..., s_n]` me mean the minimum of all the indentations of the given strings `s_1`, ..., `s_n`.

  `Data.TextBox.indentation (box)` returns the indentation of the given `box`.

  For example,

      > Data.TextBox.indentation (['one', 'two'])
      0

      > Data.TextBox.indentation (['  one', 'two'])
      0

      > Data.TextBox.indentation (['  one', '  two'])
      2

      > Data.TextBox.indentation (['  '])
      2

  Recall, that the minimum `Int.minimum([])` of an empty list is `Infinity` by definition. Accordingly, the indentation of the empty text box is

      > Data.TextBox.indentation ([])
      Infinity

---
unit
  function
name
  Data.TextBox.indent
type
  Type.lambda ([INT, BOX, BOX])
value
  function (i) {
    return function (box) {
      if (i > 0) {
        var white = Str.repeat (' ') (i);
        return List.map (function (s) { return white + s; }) (box);
      } else { // i.e. `i <= 0`
        var n = indentation (box);
        if (-i > n) {
          throw Error ("Cannot unindent the given box by `" + (-i) + "` spaces, because its own indentation is only `" + n + "`.");
        } else {
          return List.map (function (s) { return s.slice (-i); }) (box);
        }
      }
    }
  }
info
  Let `box` be a text box `[s_1, ..., s_n]` and `i` and integer, then `Data.TextBox.indent (i) (box)` returns another text box which is defined as follows:

  * If `i` is a positive integer, `Data.TextBox.indent (i) (box)` increases the indentation of `box` by `i`. In other words, the new text box is given by `[w + s_1, ..., w + s_n]`, where `w` is the string of `i` space characters.

  * If `i` is a negative integer, `Data.TextBox.indent (i) (box)` decreases the indentation of `box` by `i`. In other words, the new text box is given by `[s_1.slice(-i), ..., s_n.slice(-i)]`.

  For example,

      ...............................

---
unit
  type
name
  Data.TextBox.PARAMETER
value
  Type.model (Rec.create ({
    width      : NAT,
    height     : NAT,
    border     : Type.finite (['none', 'space', 'thin', 'thick', 'double', 'rounded']),
    horizontal : Type.finite (['left', 'right', 'center']),  // the values of the CSS `text-align` property
    vertical   : Type.finite (['top', 'bottom', 'middle'])   // the values of the CSS `vertical-align` property
  }))
info
  ...
---
unit
  type
name
  Data.TextBox.create
type
  Type.lambda ([PARAMETER, Type.list (STRING), BOX])
value
  function (param) {

    return function (strL) {

      // 1. verify that the given `strL` is a proper Text Box `tbox`
      var tbox = [];
      for (var i = 0; i < strL.length; i++) {
        var charCodeL = Str.toCharCodeList (strL [i]);
        for (var j = 0; j < charCodeL.length; j++) {
          if (charCodeL [j] < 32) {
            throw Error ( "The given String List does not make a Text Box, because the " + i + "-th string at the " +
              j + "-th position contains a Control Character (with character code " + charCodeL[j] + ")." );
          }
        }
        tbox.push (strL [i]);
      }

      // 2. reconstruct and verify all parameters
      var w0         = width  (tbox);
      var h0         = height (tbox);
      var w1         = param.width      || w0;
      var h1         = param.height     || h0;
      var border     = param.border     || 'none';
      var horizontal = param.horizontal || 'left';
      var vertical   = param.vertical   || 'top';
      if (w1 < w0)
        throw Error ("The specified parameter `width` is set to `" + w1 +
          "`, but this is below the actual width `" + w0 + "` of the given string list.");
      if (h1 < h0)
        throw Error ("The specified parameter `height` is set to `" + h1 +
          "`, but this is below the actual height `" + h0 + "` of the given string list.");

      // 3.a) normalize vertically
      var before, after; // both `$Nat`
      switch (vertical) {
        case 'top':
          before = 0;
          after  = h1 - h0;
          break;
        case 'bottom':
          before = h1 - h0;
          after  = 0;
          break;
        case 'middle':
          before = Int.floor ((h1 - h0) / 2);
          after  = Int.ceil  ((h1 - h0) / 2);
          break;
        default:
          throw Error ("`" + vertical + "` is an undefined value for the `vertical` property of the parameter record.");
      }
      for (var i = 0; i < before; i++) { tbox.unshift (""); }
      for (var i = 0; i < after ; i++) { tbox.push ("");    }

      // 3.b) normalize horizontally
      switch (horizontal) {
        case 'left':
          for (var i = 0; i < tbox.length; i++) {
            tbox[i] = tbox[i] + Str.repeat (" ") (w1 - tbox[i].length);
          };
          break;
        case 'right':
          for (var i = 0; i < tbox.length; i++) {
            tbox[i] = Str.repeat (" ") (w1 - tbox[i].length) + tbox[i];
          }
          break;
        case 'center':
          for (var i = 0; i < tbox.length; i++) {
            tbox[i] = Str.repeat (" ") (Int.floor ((w1 - tbox[i].length) / 2))
                    + tbox[i]
                    + Str.repeat (" ") (Int.ceil  ((w1 - tbox[i].length) / 2));
          }
          break;
        default:
          throw Error ("`" + horizontal + "` is an undefined value for the `horizontal` property of the parameter record.");
      }

      // 4. draw the optional border line
      switch (border) {
        case 'none':
          break;
        case 'space':
          for (var i = 0; i < tbox.length; i++) { tbox[i] = " " + tbox[i] + " "; }
          tbox.unshift (Str.repeat (" ") (w1 + 2));
          tbox.push    (Str.repeat (" ") (w1 + 2));
          break;
        case 'thin':
          for (var i = 0; i < tbox.length; i++) { tbox[i] = "│" + tbox[i] + "│"; }
          tbox.unshift ( "┌" + Str.repeat ("─") (w1) + "┐" );
          tbox.push    ( "└" + Str.repeat ("─") (w1) + "┘" );
          break;
        case 'thick':
          for (var i = 0; i < tbox.length; i++) { tbox[i] = "┃" + tbox[i] + "┃"; }
          tbox.unshift ( "┏" + Str.repeat ("━") (w1) + "┓" );
          tbox.push    ( "┗" + Str.repeat ("━") (w1) + "┛" );
          break;
        case 'double':
          for (var i = 0; i < tbox.length; i++) { tbox[i] = "║" + tbox[i] + "║"; }
          tbox.unshift ( "╔" + Str.repeat ("═") (w1) + "╗" );
          tbox.push    ( "╚" + Str.repeat ("═") (w1) + "╝" );
          break;
        case 'rounded':
          for (var i = 0; i < tbox.length; i++) { tbox[i] = "│" + tbox[i] + "│"; }
          tbox.unshift ( "╭" + Str.repeat ("─") (w1) + "╮" );
          tbox.push    ( "╰" + Str.repeat ("─") (w1) + "╯" );
          break;
        default:
          throw Error ("`TextBox.box(param)(x)` error: `" + border + "` is an undefined value for `param.border`.");
      }

      return tbox;

    }
  }
info
  `Data.TextBox.create (param) (strL)` returns a text box of the given string list `strL`, which is a proper text box (i.e. all strings of equal length) and which is decorated according to the parameters `param`.

  For example,

      > Data.TextBox.create ({}) (["Hello", "there!"])
      [ 'Hello ',
        'there!' ]

      > Data.TextBox.create ({width: 10, height: 5}) (["Hello", "there!"])
      [ 'Hello     ',
        'there!    ',
        '          ',
        '          ',
        '          ' ]

      > Data.TextBox.create ({width: 10, height: 5, horizontal: 'center', vertical: 'middle'}) (["Hello", "there!"])
      [ '          ',
        '  Hello   ',
        '  there!  ',
        '          ',
        '          ' ]

      > Data.TextBox.create ({width: 10, height: 5, horizontal: 'right', vertical: 'bottom'}) (["Hello", "there!"])
      [ '          ',
        '          ',
        '          ',
        '     Hello',
        '    there!' ]

      > Data.TextBox.create ({border: 'none'}) (["Hello", "there!"])
      [ 'Hello ',
       'there!' ]

      > Data.TextBox.create ({border: 'thin'}) (["Hello", "there!"])
      [ '┌──────┐',
        '│Hello │',
        '│there!│',
        '└──────┘' ]

      > Data.TextBox.create ({border: 'thick'}) (["Hello", "there!"])
      [ '┏━━━━━━┓',
        '┃Hello ┃',
        '┃there!┃',
        '┗━━━━━━┛' ]

      > Data.TextBox.create ({border: 'double'}) (["Hello", "there!"])
      [ '╔══════╗',
        '║Hello ║',
        '║there!║',
        '╚══════╝' ]

      > Data.TextBox.create ({border: 'rounded'}) (["Hello", "there!"])
      [ '╭──────╮',
        '│Hello │',
        '│there!│',
        '╰──────╯' ]

      > Data.TextBox.create ({border: 'space'}) (["Hello", "there!"])
      [ '        ',
        ' Hello  ',
        ' there! ',
        '        ' ]

      > Data.TextBox.create ({border: 'rounded'}) ([])
      [ '╭╮',
        '╰╯' ]

  If the given String List contains a string with a Control Character, an error is thrown:

      > Data.TextBox.create ({}) (["This is not a text box.", "The newline \n is a forbidden character."])
      Error: The given String List does not make a Text Box, because the 1-th string at the 12-th position contains a Control Character (with character code 10).

  Note, that the empty parameter record `{}` (or any other under-determined parameter record) defaults to

          { border: 'none' , horizontal: 'left', vertical: 'top', width: Data.TextBox.width(strL), height: Data.TextBox.height }

---
unit
  type
name
  Data.TextBox.GRID
value
  Type.list (Type.list (BOX))
info
  A __text box grid__ is a list of list of text boxes.
---
unit
  function
name
  Data.TextBox.gridWidth
type
  Type.lambda ([GRID, NAT])
value
  function (grid) {
    var w = 0;
    for (var i = 0; i < grid.length; i++) {
      w = Int.max (w) (grid[i].length);
    }
    return w;
  }
info
  `Data.TextBox.gridWidth (grid)` returns the number of columns in `grid`, i.e. the maximal length of its elements.
---
unit
  function
name
  Data.TextBox.gridHeight
type
  Type.lambda ([GRID, NAT])
value
  function (grid) {
    return grid.length;
  }
info
  `Data.TextBox.gridHeight (grid)` returns the number of rows in the given `grid`, which is the length of the `grid` as a list.
---
unit
  function
name
  Data.TextBox.rowHeights
type
  Type.fun ([GRID, Type.list (NAT)])
value
  function (grid) {
    var hL = []
    for (var i = 0; i < gridHeight(grid); i++) {
      var h = 0;
      for (var j = 0; j < grid[i].length; j++) {
        h = Int.max (h) (height (grid[i][j]));
      }
      hL.push (h);
    }
    return hL;
  }
info
  .....
---
unit
  function
name
  Data.TextBox.columnWidths
type
  Type.fun ([GRID, Type.list (NAT)])
value
  function (grid) {
    var wL = [];
    for (var j = 0; j < gridWidth(grid); j++) {
      var w = 0;
      for (var i = 0; i < gridHeight(grid); i++) {
        if (j < grid[i].length) {
          w = Int.max (w) (width (grid[i][j]));
        }
      }
      wL.push (w);
    }
    return wL;
  }
info
  ....
---
unit
  function
name
  Data.TextBox.fromGrid
type
  Type.lambda ([PARAMETER, GRID, BOX])
value
  function (param) {
    return function (grid) {

      // 1.a) determine the width and height of the grid
      var height = gridHeight (grid);
      var width  = gridWidth (grid);

      // 1.b) determine the row heights and colum widths
      var rowHeightL = rowHeights (grid);
      var colWidthL  = columnWidths (grid);

      // 2. generate a new grid `ngrid` with the normalized boxes of `grid`
      var p = {
        horizontal : param.horizontal,
        vertical   : param.vertical
      };
      var ngrid = [];
      for (var i = 0; i < height; i++) {
        var row = [];
        p.height = rowHeightL[i];
        for (var j = 0; j < width; j++) {
          var tbox = grid[i][j] || [];
          p.width = colWidthL[j];
          tbox = create (p) (tbox);
          row.push (tbox);
        }
        ngrid.push (row);
      }

      // 3. merge the grid into a box with borders
      var border = param.border || 'thin';
      var tbox = [];
      var line;
      switch (border) {

        case 'thin':
          // 1. head line
          line = "┌";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("─") (colWidthL [j]);
            if (j+1 < width) { line += "┬"; }
          }
          line += "┐";
          tbox.push (line);
          // 2. middle line
          line = "├";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("─") (colWidthL [j]);
            if (j+1 < width) { line += "┼"; }
          }
          line += "┤";
          // 3. the grid lines and the middle line in between
          for (var i = 0; i < height; i++) {
            for (var ii = 0; ii < rowHeightL[i]; ii++) {
              var str = "│";
              for (var j = 0; j < width; j++) {
                str += ngrid[i][j][ii];
                if (j+1 < width) { str += "│"; }
              }
              str += "│";
              tbox.push (str);
            }
            if (i+1 < height) { tbox.push (line); }
          }
          // 4. bottom line
          line = "└";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("─") (colWidthL [j]);
            if (j+1 < width) { line += "┴"; }
          }
          line += "┘";
          tbox.push (line);
          break;

        case 'thick':
          // 1. head line
          line = "┏";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("━") (colWidthL [j]);
            if (j+1 < width) { line += "┳"; }
          }
          line += "┓";
          tbox.push (line);
          // 2. middle line
          line = "┣";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("━") (colWidthL [j]);
            if (j+1 < width) { line += "╋"; }
          }
          line += "┫";
          // 3. the grid lines and the middle line inbetween
          for (var i = 0; i < height; i++) {
            for (var ii = 0; ii < rowHeightL[i]; ii++) {
              var str = "┃";
              for (var j = 0; j < width; j++) {
                str += ngrid[i][j][ii];
                if (j+1 < width) { str += "┃"; }
              }
              str += "┃";
              tbox.push (str);
            }
            if (i+1 < height) { tbox.push (line); }
          }
          // 4. bottom line
          line = "┗";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("━") (colWidthL [j]);
            if (j+1 < width) { line += "┻"; }
          }
          line += "┛";
          tbox.push (line);
          break;

        case 'double':
          // 1. head line
          line = "╔";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("═") (colWidthL [j]);
            if (j+1 < width) { line += "╦"; }
          }
          line += "╗";
          tbox.push (line);
          // 2. middle line
          line = "╠";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("═") (colWidthL [j]);
            if (j+1 < width) { line += "╬"; }
          }
          line += "╣";
          // 3. the grid lines and the middle line inbetween
          for (var i = 0; i < height; i++) {
            for (var ii = 0; ii < rowHeightL[i]; ii++) {
              var str = "║";
              for (var j = 0; j < width; j++) {
                str += ngrid[i][j][ii];
                if (j+1 < width) { str += "║"; }
              }
              str += "║";
              tbox.push (str);
            }
            if (i+1 < height) { tbox.push (line); }
          }
          // 4. bottom line
          line = "╚";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("═") (colWidthL [j]);
            if (j+1 < width) { line += "╩"; }
          }
          line += "╝";
          tbox.push (line);
          break;

        case 'rounded':
          // 1. head line
          line = "╭";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("─") (colWidthL [j]);
            if (j+1 < width) { line += "┬"; }
          }
          line += "╮";
          tbox.push (line);
          // 2. middle line
          line = "├";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("─") (colWidthL [j]);
            if (j+1 < width) { line += "┼"; }
          }
          line += "┤";
          // 3. the grid lines and the middle line inbetween
          for (var i = 0; i < height; i++) {
            for (var ii = 0; ii < rowHeightL[i]; ii++) {
              var str = "│";
              for (var j = 0; j < width; j++) {
                str += ngrid[i][j][ii];
                if (j+1 < width) { str += "│"; }
               }
              str += "│";
              tbox.push (str);
            }
            if (i+1 < height) { tbox.push (line); }
          }
          // 4. bottom line
          line = "╰";
          for (var j = 0; j < width; j++) {
            line += Str.repeat ("─") (colWidthL [j]);
            if (j+1 < width) { line += "┴"; }
          }
          line += "╯";
          tbox.push (line);
          break;

        case 'space':
          // 1. head line
          line = " ";
          for (var j = 0; j < width; j++) {
            line += Str.repeat (" ") (colWidthL [j]);
            if (j+1 < width) { line += " "; }
          }
          line += " ";
          tbox.push (line);
          // 2. middle line
          line = " ";
          for (var j = 0; j < width; j++) {
            line += Str.repeat (" ") (colWidthL [j]);
            if (j+1 < width) { line += " "; }
          }
          line += " ";
          // 3. the grid lines and the middle line inbetween
          for (var i = 0; i < height; i++) {
            for (var ii = 0; ii < rowHeightL[i]; ii++) {
              var str = " ";
              for (var j = 0; j < width; j++) {
                str += ngrid[i][j][ii];
                if (j+1 < width) { str += " "; }
              }
              str += " ";
              tbox.push (str);
            }
            if (i+1 < height) { tbox.push (line); }
          }
          // 4. bottom line
          line = " ";
          for (var j = 0; j < width; j++) {
            line += Str.repeat (" ") (colWidthL [j]);
            if (j+1 < width) { line += " "; }
          }
          line += " ";
          tbox.push (line);
          break;

        case 'none':
          for (var i = 0; i < height; i++) {
            for (var ii = 0; ii < rowHeightL[i]; ii++) {
              var str = "";
              for (var j = 0; j < width; j++) {
                str += ngrid[i][j][ii];
              }
              tbox.push (str);
            }
          }
          break;

        default:
          throw Error ("The `border` parameter value `" + border + "` is undefined." );
      }

      return tbox;
    };
  }
info
  ....
---
---
// end Data.TextBox
---
---
