... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.using
 [library
  [lux (.except)
   [abstract
    [equality (.only Equality)]
    [hash (.only Hash)]]
   [control
    ["[0]" pipe]]
   [function
    [predicate (.only Predicate)]]
   [data
    [text (.only Injection)
     ["%" \\injection]]]
   [math
    ["[0]" random (.only Random)]
    [number
     [/64
      ["n" natural]
      ["i" integer]]]]
   [macro
    ["[0]" template]]
   [compiler
    ["@[0]" type (.only Register Variable)]]]]
 [//
  ["[0]" register]])

(the .public equality
  (Equality Variable)
  (implementation
   (the (= expected actual)
     (`` (when [expected actual]
           (,, (template.with [<tag>]
                 [[{<tag> expected'} {<tag> actual'}]
                  (n.= expected' actual')]

                 [[@type.:Local]
                  [@type.:Foreign]]))

           _
           false)))))

(alias [=]
       ..equality)

(the .public hash
  (Hash Variable)
  (implementation
   (the equality
     ..equality)
   
   (the hash
     (|>> (pipe.when
            (,, (template.with [<factor> <tag>]
                  [{<tag> register}
                   (|> register
                       (by n.hash hash)
                       (n.x <factor>))]

                  [[2 @type.:Local]
                   [3 @type.:Foreign]])))
          ``))))

(the .public self
  (template.macro (self)
    [{@type.:Local register.first}]))

(the .public self?
  (Predicate Variable)
  (|>> (pipe.when
         (..self)
         true

         _
         false)))

(the .public as_text
  (Injection Variable)
  (|>> (pipe.when
         {@type.:Local local}
         (text "+" (%.natural local))
         
         {@type.:Foreign foreign}
         (text "-" (%.natural foreign)))))

(the .public random
  (Random Variable)
  (all random.or
       random.natural
       random.natural
       ))
