[
  {
    "path": ".gitignore",
    "content": "_build\nerl_crash.dump\ndoc/_site\ndeps\nebin\n"
  },
  {
    "path": "LICENSE.md",
    "content": "BSD License\n===========\n\nCopyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright\n  notice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in the\n  documentation and/or other materials provided with the distribution.\n* Neither the name of Francesca Gangemi, Corrado Santoro may be used\n  to endorse or promote products derived from this software without\n  specific prior written permission.\n\n\nTHIS SOFTWARE IS PROVIDED BY Francesca Gangemi AND Corrado Santoro ``AS\nIS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "SERESYE - Swarm oriented ERlang Expert SYstem Engine\n====================================================\n\nIntroduction\n------------\n\nSERESYE is a Rete based rules engine written in Erlang, descended\ndirectly from the Eresye project by Francesca Gangemi and Corrado\nSantoro. In the following article we will describe how to use the\nsystem.\n\nAs it is widely known, a rule-based system is composed by a\n**knowledge base**, which stores a set of *facts* representing the\n'universe of discourse' of a given application, and a set of\n**production rules**, which are used to infer knowledge and/or reason\nabout the knowledge. A rule is activated when one or more facts match\nthe template(s) given in the rule declaration: in such a case, the\nbody of the rule contains a code that is thus executed\n\nIn SERESYE, *facts* are expressed by means of Erlang tuples or records,\nwhile rules are written using standard Erlang function clauses, whose\ndeclaration reports, in the clause head, the facts or fact templates\nthat have to be matched for the rule to be activated and executed.\n\nFor more information about SERESYE please refer to the paper docs directory.\n\nFor more information about rule-based inference engines and expert\nsystems, you can refer to the book: *S. Russell and\nP. Norvig. **Artificial Intelligence: A Modern Approach/2E.** Prentice\nHall, 2003.*\n\nTo write an AI application with SERESYE the following steps have to be\nperformed:\n\n1. Indentify your universe of discourse and determine the facts that\n   have to be used to represent such a world;\n\n2. Indentify the rules that you need and write them by using, e.g.\n   first-order-logic predicates or even natural language;\n\n3. Implement the system by writing your rules as Erlang function\n   clauses, according to the modality required by SERESYE.\n\n\nThe Application: the Domain of Relatives\n----------------------------------------\n\nWe will design a system able to derive new knowledge using some\ninference rules and starting from a small set; as a sample\napplication, we chose the domain of relatives: we will start from some\nbase concepts, such as *parent*, *male* and *female*, and then, by\nmeans of a proper set of rules, we will derive the concepts of\n*mother*, *father*, *sister*, *brother*, *grandmother* and\n*grandfather*.\n\nAccording to the list above, we will first derive the facts that will be\nused to represent our concepts. Given the set of relationships above, they\nwill be represented by means of the following facts:\n\n<table border=\"1\" align=\"center\">\n<thead>\n  <tr>\n    <td>#</td>\n    <td>Concept</td>\n    <td>Fact / Erlang tuple</td>\n  </tr>\n</thead>\n<tbody>\n  <tr>\n    <td>1</td>\n    <td>X is male</td>\n    <td><tt>{male, X}</tt></td>\n  </tr>\n  <tr>\n    <td>2</td>\n    <td>X is female</td>\n    <td><tt>{female, X}</tt></td>\n  </tr>\n  <tr>\n    <td>3</td>\n    <td>X is Y's parent</td>\n    <td><tt>{parent, X, Y}</tt></td>\n  </tr>\n  <tr>\n    <td>4</td>\n    <td>X is Y's mother</td>\n    <td><tt>{mother, X, Y}</tt></td>\n  </tr>\n  <tr>\n    <td>5</td>\n    <td>X is Y's father</td>\n    <td><tt>{father, X, Y}</tt></td>\n  </tr>\n  <tr>\n    <td>6</td>\n    <td>X is Y's sister</td>\n    <td><tt>{sister, X, Y}</tt></td>\n  </tr>\n  <tr>\n    <td>7</td>\n    <td>X is Y's brother</td>\n    <td><tt>{brother, X, Y}</tt></td>\n  </tr>\n  <tr>\n    <td>8</td>\n    <td>X is Y's grandmother</td>\n    <td><tt>{grandmother, X, Y}</tt></td>\n  </tr>\n  <tr>\n    <td>9</td>\n    <td>X is Y's grandfather</td>\n    <td><tt>{grandfather, X, Y}</tt></td>\n  </tr>\n</tbody>\n</table>\n\nConcepts 1, 2 and 3 will be used as a base to derive the other ones.\n\nDeriving new concepts by means of rules\n---------------------------------------\n\n#### Concept: mother\n\nThe rule to derive the concept of mother is quite\nstraightforward:\n\n    if X is female and X is Y's parent then X is Y's mother.\n\nFrom the point of view of SERESYE, since knowledge is stored in the\n*knowledge base* of the engine, the rule above is translated into the\nfollowing one: *if the facts {female, X} and {parent, X, Y} are\n*asserted* in the knowledge base, then we assert the fact {mother, X,\nY}.\n\nThe rule *mother* can be thus written as follows:\n\n    %%\n    %% if (X is female) and (X is Y's parent) then (X is Y's mother)\n    %%\n    mother (Engine, {female, X}, {parent, X, Y}) ->\n      seresye:assert (Engine, {mother, X, Y}).\n\n\n#### Concept: father\n\nThis concept can be easily derived by means of the following rule:\n\n    %%\n    %% if (X is male) and (X is Y's parent) then (X is Y's father)\n    %%\n    father (Engine, {male, X}, {parent, X, Y}) ->\n      seresye:assert (Engine, {father, X, Y}).\n\n\n#### Concept: sister\n\n This concept can be expressed by the following rule:\n\n    if Y and Z have the same parent and Z is female, then Z\n    is the Y's sister.\n\nThe SERESYE rule used to map this concept is:\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is female)\n    %%    then (Z is Y's sister)\n    %%\n    sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->\n      seresye:assert (Engine, {sister, Z, Y}).\n\n\nPlease note the guard, which is needed to ensure that when Y and Z are\nbound to the same value, the rule is not activated (indeed this is\npossible since the same fact can match both the first and second\n'parent' pattern).\n\n#### Concept: brother\n\nGiven the previous one, this concept is now quite simple to\nimplement:\n\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is male)\n    %%    then (Z is Y's brother)\n    %%\n    brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->\n      seresye:assert (Engine, {brother, Z, Y}).\n\n\n#### Concepts: grandmother and grandfather\n\nThe former concept can be expressed by means of the rule:\n\n    if X is Y's mother and Y is Z's parent, then X is Z's\n    grandmother.</u>* The latter concept is now obvious.\n\nBoth can be implemented using the following SERESYE rules:\n\n    %%\n    %% if (X is Y's mother) and (Y is Z's parent)\n    %%    then (X is Z's grandmother)\n    %%\n    grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) ->\n      seresye:assert (Engine, {grandmother, X, Z}).\n\n    %%\n    %% if (X is Y's father) and (Y is Z's parent)\n    %%    then (X is Z's grandfather)\n    %%\n    grandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->\n      seresye:assert (Engine, {grandfather, X, Z}).\n\n\nInstantiating the Engine and Populating the Knowledge Base\n----------------------------------------------------------\n\nAfter writing the rules, we need to:\n\n- define the rules to seresye\n- instantiate the engine;\n- populate the knowledge base with a set of initial facts.\n\nWe define the rules to SERESYE by defined a 'rules' attribute at the\nstart of the module.\n\n    %%%\n    %%% relatives.erl\n    %%%\n    -module (relatives).\n\n    -export([father/3, grandfather/3, grandmother/3,\n             mother/3, brother/4, sister/4, start/0]).\n\n    -rules([mother, father, brother, sister, grandfather,\n            grandmother]).\n\nWe continue on to instantiate the engine and popoulate the knowledge\nbase in the function *start* below:\n\n    start () ->\n      application:start(seresye) % Only if it is not already started\n      seresye:start(relatives),\n      seresye:add_rules(relatives, ?MODULE)\n\n      seresye:assert(relatives,\n                     [{male, bob}, {male, corrado}, {male, mark}, {male, caesar},\n                      {female, alice}, {female, sara}, {female, jane}, {female, anna},\n                      {parent, jane, bob}, {parent, corrado, bob},\n                      {parent, jane, mark}, {parent, corrado, mark},\n                      {parent, jane, alice}, {parent, corrado, alice},\n                      {parent, bob, caesar}, {parent, bob, anna},\n                      {parent, sara, casear}, {parent, sara, anna}]),\n      ok.\n\nAs the listing reports, creating a new SERESYE engine implies to call\nthe function *seresye:start/1*, giving the name of the engine to be\ncreated\n\nThen, we have to add the rules to the engine by using the function\n*seresye:add_rule/2*: it takes two arguments, the name of the engine\nand a tuple representing the function in the form *{Module,\nFuncName}*; obviously the function *Module:FuncName* must be\nexported. Function *add_rule* has to be called for each rule that has\nto be added; for this reason, the code above has an iteration over the\nlist of rules written before.\n\nFinally, we populate the inference engine with a set of sample facts\nby giving them, in a list, to the function *seresye:assert/2*.  To test\nour rules, we considered the relationships in the Figure below and\nassert only the facts for *male*, *female* and *parent*.\n\nTesting the application\n-----------------------\n\nThe final complete code of our AI application is thus the following:\n\n\n    %%%\n    %%% relatives.erl\n    %%%\n    -module (relatives).\n    -export([father/3, grandfather/3, grandmother/3,\n             mother/3, brother/4, sister/4, start/0]).\n\n    %%\n    %% if (X is female) and (X is Y's parent) then (X is Y's mother)\n    %%\n    mother(Engine, {female, X}, {parent, X, Y}) ->\n      seresye:assert(Engine, {mother, X, Y}).\n\n    %%\n    %% if (X is male) and (X is Y's parent) then (X is Y's father)\n    %%\n    father(Engine, {male, X}, {parent, X, Y}) ->\n      seresye:assert(Engine, {father, X, Y}).\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is female)\n    %%    then (Z is Y's sister)\n    %%\n    sister(Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->\n      seresye:assert(Engine, {sister, Z, Y}).\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is male)\n    %%    then (Z is Y's brother)\n    %%\n    brother(Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->\n      seresye:assert(Engine, {brother, Z, Y}).\n\n    %%\n    %% if (X is Y's father) and (Y is Z's parent)\n    %%    then (X is Z's grandfather)\n    %%\n    grandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->\n      seresye:assert (Engine, {grandfather, X, Z}).\n\n    %%\n    %% if (X is Y's mother) and (Y is Z's parent)\n    %%    then (X is Z's grandmother)\n    %%\n    grandmother(Engine, {mother, X, Y}, {parent, Y, Z}) ->\n      seresye:assert(Engine, {grandmother, X, Z}).\n\n    start () ->\n      application:start(seresye),\n      seresye:start (relatives),\n      seresye:add_rules(relatives, ?MODULE)\n\n      seresye:assert (relatives,\n                     [{male, bob},\n                      {male, corrado},\n                      {male, mark},\n                      {male, caesar},\n                      {female, alice},\n                      {female, sara},\n                      {female, jane},\n                      {female, anna},\n                      {parent, jane, bob},\n                      {parent, corrado, bob},\n                      {parent, jane, mark},\n                      {parent, corrado, mark},\n                      {parent, jane, alice},\n                      {parent, corrado, alice},\n                      {parent, bob, caesar},\n                      {parent, bob, anna},\n                      {parent, sara, casear},\n                      {parent, sara, anna}]),\n      ok.\n\nNow it's time to test our application:\n\n\n    Erlang (BEAM) emulator version 5.5 [source] [async-threads:0] [hipe]\n\n    Eshell V5.5  (abort with ^G)\n    1> c(relatives).\n    {ok,relatives}\n    2> relatives:start().\n    ok\n    3>\n\nFollowing the call to function *relatives:start/0*, the engine is\ncreated and populated; if no errors occurred, the rules should have\nbeen processed and the new facts derived. To check this, we can use\nthe function *seresye:get_kb/1*, which returns the list of facts\nasserted into the knowledge base of a given engine:\n\n\n    4> seresye:get_kb(relatives).\n    [{brother,bob,mark},\n     {sister,alice,bob},\n     {sister,alice,mark},\n     {brother,bob,alice},\n     {brother,mark,alice},\n     {grandmother,jane,caesar},\n     {grandfather,corrado,caesar},\n     {grandmother,jane,anna},\n     {grandfather,corrado,anna},\n     {sister,anna,caesar},\n     {brother,caesar,anna},\n     {sister,anna,casear},\n     {mother,sara,anna},\n     {mother,sara,casear},\n     {parent,sara,anna},\n     {father,bob,anna},\n     {parent,sara,casear},\n     {father,bob,caesar},\n     {parent,bob,anna},\n     {father,corrado,alice},\n     {parent,bob,caesar},\n     {mother,jane,alice},\n     {parent,corrado,alice},\n     {father,corrado,mark},\n     {parent,jane,alice},\n     {mother,jane,mark},\n     {parent,corrado|...},\n     {brother|...},\n     {...}|...]\n    5>\n\nThe presence of facts representing concepts like *father*, *sister*,\netc., proves that the rules seems to be working as expected.\n\nWe can however query the knowledge base using specific fact templates.\nFor example, if we want to know who are Alice's brothers, we can use\nthe function *seresye:query_kb/2* as follows:\n\n\n    6> seresye:query_kb(relatives, {brother, '_', alice}).\n    [{brother,bob,alice},{brother,mark,alice}]\n    7>\n\nThe facts returned conform to the relationships depicted in the figure\nabove, thus proving that the rules written are really working.\n\nAs the example shows, function *seresye:query_kb/2* takes the engine\nname as the first argument, while, for the second parameter, a tuple\nhas to be specified, representing the fact template to be matched; in\nsuch a tuple, the atom *'_'* plays the role of a wildcard. However, to\nspecify a more complex matching, a *fun* can be used as a tuple\nelement; this *fun* has to return a boolean value which indicates if\nthe element matches the template. For example, to select both Alice's\nand Anna's brothers, we can use the following function call:\n\n\n    7> seresye:query_kb(relatives, {brother, '_', fun (X) -> (X == alice) or (X == anna) end}).\n    [{brother,bob,alice},{brother,mark,alice},{brother,caesar,anna}]\n    8>\n\n\nConclusions\n-----------\n\nThis HowTo not only shows how to use the SERESYE engine to write an AI\napplication, but also highlights the versatility of the Erlang language:\nthe characteristics of functional and symbolic programming, together with\nthe possibility of performing *introspection* of function declaration,\ncan be successfully exploited for application domains which are completely\nnew for Erlang but can surely be very interesting.\n"
  },
  {
    "path": "do-gh-pages",
    "content": "#!/bin/sh\n\nPARENT_SHA=$(git show-ref -s refs/heads/gh-pages)\nDOC_SHA=$(git ls-tree -d HEAD doc | awk '{print $3}')\nNEW_COMMIT=$(echo \"Auto-update docs.\" | git commit-tree $DOC_SHA -p $PARENT_SHA)\ngit update-ref refs/heads/gh-pages $NEW_COMMIT\n"
  },
  {
    "path": "doc/CNAME",
    "content": "seresye.org"
  },
  {
    "path": "doc/_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html lang='en'>\n  <head>\n    <title>{{ page.title }}</title>\n    <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />\n    <!--[if lt IE 9]><script type='text/javascript' src='assets/javascript/html5.js'></script><![endif]-->\n    <script type='text/javascript' src='assets/javascript/prettify.js'></script>\n    <link rel='stylesheet' type='text/css' href='assets/css/skeleton/stylesheets/base.css' />x\n    <link rel='stylesheet' type='text/css' href='assets/css/skeleton/stylesheets/skeleton.css' />\n    <link rel='stylesheet' type='text/css' href='assets/css/prettify.css' />\n    <link rel='stylesheet' type='text/css' href='assets/css/style.css' />\n    <link rel='stylesheet' type='text/css' href='assets/css/code.css' />\n  </head>\n\n  <body onload='prettyPrint()'>\n    <div class='container'>\n      <header class='sixteen columns'>\n        <div class='nine columns alpha'>\n          <h1>SERESYE - {{ page.title }}</h1>\n        </div>\n\n        <div class='six columns offset-by-one omega'>\n          <a href='https://github.com/downloads/afiniate/seresye'\n             class='download-button'>\n            Download\n            <span>Latest version from GitHub</span>\n          </a>\n        </div>\n      </header>\n\n      <div class=\"menu sixteen columns\">\n        <ul>\n          <li><a href=\"/seresye/\">Home</a></li>\n          <li><a href=\"/seresye/Domain_Of_Relatives_Example.pdf\">\n              Domain of Relatives Example (out of date)</a></li>\n          <li><a href=\"/seresye/Eresye_Paper.pdf\">\n              Eresye Paper (out of date)</a></li>\n        </ul>\n        <br style=\"clear:left\"/>\n      </div>\n\n      <div class='sixteen columns'>\n\n        {{content}}\n\n      </div>\n\n      <div class='sixteen columns'>\n\n\n      </div>\n    </div>\n\n    <footer>\n      <div class='container'>\n        <div class='ten columns offset-by-three repo-author'>\n          <img src='http://www.afiniate.com/uploads/9/1/6/3/9163759/3030558.png?364'\n               class='repo-author-logo' />\n          <a href=\"http://www.twitter.com/afiniate\">\n            <img src=\"http://twitter-badges.s3.amazonaws.com/twitter-a.png\"\n                 alt=\"Follow Afiniate on Twitter\"/>\n          </a>\n          <p>\n            Aﬁniate has proven expertise in delivering innovative,\n            mission-critical enterprise solutions, including\n            large-scale distributed systems to Fortune 500 companies\n            like Amazon.com and leading edge high-frequency trading\n            systems to private brokerages like PEAK6 Investments.\n\n            We are focused on applying that expertise in developing\n            intelligence and analytic systems for the banking\n            industry, and using that technology to help already\n            successful ﬁnancial institutions to fully leverage their\n            valuable, but underutilized, data in ways that drive\n            increased revenue, improved operational efﬁciencies,\n            insight-based decision making, and enhanced customer\n            satisfaction.\n          </p>\n        </div>\n\n        <div class='sixteen columns credits'>\n          <p>GitHub release template built with HTML5, CSS3 and JS\n            by <a href='http://fublo.net'>Fublo</a></p>\n        </div>\n      </div>\n    </footer>\n\n    <a href='https://github.com/afiniate/seresye'\n       class='github-ribbon'><img src='assets/images/github-ribbons/red.png'\n                                  /></a>\n  </body>\n</html>\n"
  },
  {
    "path": "doc/assets/css/code.css",
    "content": ".highlight .hll { background-color: #ffffcc }\n.highlight  { background: #ffffff; }\n.highlight .c { color: #999988; font-style: italic } /* Comment */\n.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */\n.highlight .k { font-weight: bold } /* Keyword */\n.highlight .o { font-weight: bold } /* Operator */\n.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */\n.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */\n.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */\n.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */\n.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */\n.highlight .ge { font-style: italic } /* Generic.Emph */\n.highlight .gr { color: #aa0000 } /* Generic.Error */\n.highlight .gh { color: #999999 } /* Generic.Heading */\n.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */\n.highlight .go { color: #888888 } /* Generic.Output */\n.highlight .gp { color: #555555 } /* Generic.Prompt */\n.highlight .gs { font-weight: bold } /* Generic.Strong */\n.highlight .gu { color: #aaaaaa } /* Generic.Subheading */\n.highlight .gt { color: #aa0000 } /* Generic.Traceback */\n.highlight .kc { font-weight: bold } /* Keyword.Constant */\n.highlight .kd { font-weight: bold } /* Keyword.Declaration */\n.highlight .kn { font-weight: bold } /* Keyword.Namespace */\n.highlight .kp { font-weight: bold } /* Keyword.Pseudo */\n.highlight .kr { font-weight: bold } /* Keyword.Reserved */\n.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */\n.highlight .m { color: #009999 } /* Literal.Number */\n.highlight .s { color: #bb8844 } /* Literal.String */\n.highlight .na { color: #008080 } /* Name.Attribute */\n.highlight .nb { color: #999999 } /* Name.Builtin */\n.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */\n.highlight .no { color: #008080 } /* Name.Constant */\n.highlight .ni { color: #800080 } /* Name.Entity */\n.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */\n.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */\n.highlight .nn { color: #555555 } /* Name.Namespace */\n.highlight .nt { color: #000080 } /* Name.Tag */\n.highlight .nv { color: #008080 } /* Name.Variable */\n.highlight .ow { font-weight: bold } /* Operator.Word */\n.highlight .w { color: #bbbbbb } /* Text.Whitespace */\n.highlight .mf { color: #009999 } /* Literal.Number.Float */\n.highlight .mh { color: #009999 } /* Literal.Number.Hex */\n.highlight .mi { color: #009999 } /* Literal.Number.Integer */\n.highlight .mo { color: #009999 } /* Literal.Number.Oct */\n.highlight .sb { color: #bb8844 } /* Literal.String.Backtick */\n.highlight .sc { color: #bb8844 } /* Literal.String.Char */\n.highlight .sd { color: #bb8844 } /* Literal.String.Doc */\n.highlight .s2 { color: #bb8844 } /* Literal.String.Double */\n.highlight .se { color: #bb8844 } /* Literal.String.Escape */\n.highlight .sh { color: #bb8844 } /* Literal.String.Heredoc */\n.highlight .si { color: #bb8844 } /* Literal.String.Interpol */\n.highlight .sx { color: #bb8844 } /* Literal.String.Other */\n.highlight .sr { color: #808000 } /* Literal.String.Regex */\n.highlight .s1 { color: #bb8844 } /* Literal.String.Single */\n.highlight .ss { color: #bb8844 } /* Literal.String.Symbol */\n.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */\n.highlight .vc { color: #008080 } /* Name.Variable.Class */\n.highlight .vg { color: #008080 } /* Name.Variable.Global */\n.highlight .vi { color: #008080 } /* Name.Variable.Instance */\n.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */\n"
  },
  {
    "path": "doc/assets/css/prettify.css",
    "content": ".pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}"
  },
  {
    "path": "doc/assets/css/skeleton/404.html",
    "content": "<!DOCTYPE html>\n<!--[if lt IE 7 ]><html class=\"ie ie6\" lang=\"en\"> <![endif]-->\n<!--[if IE 7 ]><html class=\"ie ie7\" lang=\"en\"> <![endif]-->\n<!--[if IE 8 ]><html class=\"ie ie8\" lang=\"en\"> <![endif]-->\n<!--[if (gte IE 9)|!(IE)]><!--><html lang=\"en\"> <!--<![endif]-->\n<head>\n\n\t<!-- Basic Page Needs\n  ================================================== -->\n\t<meta charset=\"utf-8\">\n\t<title>Your Page Title Here :)</title>\n\t<meta name=\"description\" content=\"\">\n\t<meta name=\"author\" content=\"\">\n\t<!--[if lt IE 9]>\n\t\t<script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"></script>\n\t<![endif]-->\n\n\t<!-- Mobile Specific Metas\n  ================================================== -->\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n\n\t<!-- CSS\n  ================================================== -->\n\t<link rel=\"stylesheet\" href=\"stylesheets/base.css\">\n\t<link rel=\"stylesheet\" href=\"stylesheets/skeleton.css\">\n\t<link rel=\"stylesheet\" href=\"stylesheets/layout.css\">\n\n\t<!-- Favicons\n\t================================================== -->\n\t<link rel=\"shortcut icon\" href=\"images/favicon.ico\">\n\t<link rel=\"apple-touch-icon\" href=\"images/apple-touch-icon.png\">\n\t<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"images/apple-touch-icon-72x72.png\">\n\t<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"images/apple-touch-icon-114x114.png\">\n\n</head>\n<body>\n\n\t<!-- Primary Page Layout\n\t================================================== -->\n\t<div class=\"container\">\n\t\t<h1 style=\"margin-top: 100px; text-align:center\">Sorry. Couldn't Find That Page!</h1>\n\t</div>\n\n<!-- End Document\n================================================== -->\n</body>\n</html>"
  },
  {
    "path": "doc/assets/css/skeleton/index.html",
    "content": "<!DOCTYPE html>\n<!--[if lt IE 7 ]><html class=\"ie ie6\" lang=\"en\"> <![endif]-->\n<!--[if IE 7 ]><html class=\"ie ie7\" lang=\"en\"> <![endif]-->\n<!--[if IE 8 ]><html class=\"ie ie8\" lang=\"en\"> <![endif]-->\n<!--[if (gte IE 9)|!(IE)]><!--><html lang=\"en\"> <!--<![endif]-->\n<head>\n\n\t<!-- Basic Page Needs\n  ================================================== -->\n\t<meta charset=\"utf-8\">\n\t<title>Your Page Title Here :)</title>\n\t<meta name=\"description\" content=\"\">\n\t<meta name=\"author\" content=\"\">\n\t<!--[if lt IE 9]>\n\t\t<script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"></script>\n\t<![endif]-->\n\n\t<!-- Mobile Specific Metas\n  ================================================== -->\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\">\n\n\t<!-- CSS\n  ================================================== -->\n\t<link rel=\"stylesheet\" href=\"stylesheets/base.css\">\n\t<link rel=\"stylesheet\" href=\"stylesheets/skeleton.css\">\n\t<link rel=\"stylesheet\" href=\"stylesheets/layout.css\">\n\n\t<!-- Favicons\n\t================================================== -->\n\t<link rel=\"shortcut icon\" href=\"images/favicon.ico\">\n\t<link rel=\"apple-touch-icon\" href=\"images/apple-touch-icon.png\">\n\t<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"images/apple-touch-icon-72x72.png\">\n\t<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"images/apple-touch-icon-114x114.png\">\n\n</head>\n<body>\n\n\n\n\t<!-- Primary Page Layout\n\t================================================== -->\n\n\t<!-- Delete everything in this .container and get started on your own site! -->\n\n\t<div class=\"container\">\n\t\t<div class=\"sixteen columns\">\n\t\t\t<h1 class=\"remove-bottom\" style=\"margin-top: 40px\">Skeleton</h1>\n\t\t\t<h5>Version 1.1</h5>\n\t\t\t<hr />\n\t\t</div>\n\t\t<div class=\"one-third column\">\n\t\t\t<h3>About Skeleton?</h3>\n\t\t\t<p>Skeleton is a small collection of well-organized CSS &amp; JS files that can help you rapidly develop sites that look beautiful at any size, be it a 17\" laptop screen or an iPhone. It's based on a responsive grid, but also provides very basic CSS for typography, buttons, tabs, forms and media queries. Go ahead, resize this super basic page to see the grid in action.</p>\n\t\t</div>\n\t\t<div class=\"one-third column\">\n\t\t\t<h3>Three Core Principles</h3>\n\t\t\t<p>Skeleton is built on three core principles:</p>\n\t\t\t<ul class=\"square\">\n\t\t\t\t<li><strong>A Responsive Grid Down To Mobile</strong>: Elegant scaling from a browser to tablets to mobile.</li>\n\t\t\t\t<li><strong>Fast to Start</strong>: It's a tool for rapid development with best practices</li>\n\t\t\t\t<li><strong>Style Agnostic</strong>: It provides the most basic, beautiful styles, but is meant to be overwritten.</li>\n\t\t\t</ul>\n\t\t</div>\n\t\t<div class=\"one-third column\">\n\t\t\t<h3>Docs &amp; Support</h3>\n\t\t\t<p>The easiest way to really get started with Skeleton is to check out the full docs and info at <a href=\"http://www.getskeleton.com\">www.getskeleton.com.</a>. Skeleton is also open-source and has a <a href=\"https://github.com/dhgamache/skeleton\">project on git</a>, so check that out if you want to report bugs or create a pull request. If you have any questions, thoughts, concerns or feedback, please don't hesitate to email me at <a href=\"mailto:hi@getskeleton.com\">hi@getskeleton.com</a>.</p>\n\t\t</div>\n\n\t</div><!-- container -->\n\n\n\n\t<!-- JS\n\t================================================== -->\n\t<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js\"></script>\n\t<script src=\"javascripts/tabs.js\"></script>\n\n<!-- End Document\n================================================== -->\n</body>\n</html>"
  },
  {
    "path": "doc/assets/css/skeleton/javascripts/tabs.js",
    "content": "/*\n* Skeleton V1.1\n* Copyright 2011, Dave Gamache\n* www.getskeleton.com\n* Free to use under the MIT license.\n* http://www.opensource.org/licenses/mit-license.php\n* 8/17/2011\n*/\n\n\n$(document).ready(function() {\n\n\t/* Tabs Activiation\n\t================================================== */\n\n\tvar tabs = $('ul.tabs');\n\n\ttabs.each(function(i) {\n\n\t\t//Get all tabs\n\t\tvar tab = $(this).find('> li > a');\n\t\ttab.click(function(e) {\n\n\t\t\t//Get Location of tab's content\n\t\t\tvar contentLocation = $(this).attr('href');\n\n\t\t\t//Let go if not a hashed one\n\t\t\tif(contentLocation.charAt(0)==\"#\") {\n\n\t\t\t\te.preventDefault();\n\n\t\t\t\t//Make Tab Active\n\t\t\t\ttab.removeClass('active');\n\t\t\t\t$(this).addClass('active');\n\n\t\t\t\t//Show Tab Content & add active class\n\t\t\t\t$(contentLocation).show().addClass('active').siblings().hide().removeClass('active');\n\n\t\t\t}\n\t\t});\n\t});\n});"
  },
  {
    "path": "doc/assets/css/skeleton/robots.txt",
    "content": "# www.robotstxt.org/\n# www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449\n\nUser-agent: *\n\n"
  },
  {
    "path": "doc/assets/css/skeleton/stylesheets/base.css",
    "content": "/*\n* Skeleton V1.1\n* Copyright 2011, Dave Gamache\n* www.getskeleton.com\n* Free to use under the MIT license.\n* http://www.opensource.org/licenses/mit-license.php\n* 8/17/2011\n*/\n\n\n/* Table of Content\n==================================================\n\t#Reset & Basics\n\t#Basic Styles\n\t#Site Styles\n\t#Typography\n\t#Links\n\t#Lists\n\t#Images\n\t#Buttons\n\t#Tabs\n\t#Forms\n\t#Misc */\n\n\n/* #Reset & Basics (Inspired by E. Meyers)\n================================================== */\n\thtml, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tborder: 0;\n\t\tfont-size: 100%;\n\t\tfont: inherit;\n\t\tvertical-align: baseline; }\n\tarticle, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {\n\t\tdisplay: block; }\n\tbody {\n\t\tline-height: 1; }\n\tol, ul {\n\t\tlist-style: none; }\n\tblockquote, q {\n\t\tquotes: none; }\n\tblockquote:before, blockquote:after,\n\tq:before, q:after {\n\t\tcontent: '';\n\t\tcontent: none; }\n\ttable {\n\t\tborder-collapse: collapse;\n\t\tborder-spacing: 0; }\n\n\n/* #Basic Styles\n================================================== */\n\tbody {\n\t\tbackground: #fff;\n\t\tfont: 14px/21px \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n\t\tcolor: #444;\n\t\t-webkit-font-smoothing: antialiased; /* Fix for webkit rendering */\n\t\t-webkit-text-size-adjust: 100%;\n }\n\n\n/* #Typography\n================================================== */\n\th1, h2, h3, h4, h5, h6 {\n\t\tcolor: #181818;\n\t\tfont-family: \"Georgia\", \"Times New Roman\", Helvetica, Arial, sans-serif;\n\t\tfont-weight: normal; }\n\th1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }\n\th1 { font-size: 46px; line-height: 50px; margin-bottom: 14px;}\n\th2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; }\n\th3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; }\n\th4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; }\n\th5 { font-size: 17px; line-height: 24px; }\n\th6 { font-size: 14px; line-height: 21px; }\n\t.subheader { color: #777; }\n\n\tp { margin: 0 0 20px 0; }\n\tp img { margin: 0; }\n\tp.lead { font-size: 21px; line-height: 27px; color: #777;  }\n\n\tem { font-style: italic; }\n\tstrong { font-weight: bold; color: #333; }\n\tsmall { font-size: 80%; }\n\n/*\tBlockquotes  */\n\tblockquote, blockquote p { font-size: 17px; line-height: 24px; color: #777; font-style: italic; }\n\tblockquote { margin: 0 0 20px; padding: 9px 20px 0 19px; border-left: 1px solid #ddd; }\n\tblockquote cite { display: block; font-size: 12px; color: #555; }\n\tblockquote cite:before { content: \"\\2014 \\0020\"; }\n\tblockquote cite a, blockquote cite a:visited, blockquote cite a:visited { color: #555; }\n\n\thr { border: solid #ddd; border-width: 1px 0 0; clear: both; margin: 10px 0 30px; height: 0; }\n\n\n/* #Links\n================================================== */\n\ta, a:visited { color: #333; text-decoration: underline; outline: 0; }\n\ta:hover, a:focus { color: #000; }\n\tp a, p a:visited { line-height: inherit; }\n\n\n/* #Lists\n================================================== */\n\tul, ol { margin-bottom: 20px; }\n\tul { list-style: none outside; }\n\tol { list-style: decimal; }\n\tol, ul.square, ul.circle, ul.disc { margin-left: 30px; }\n\tul.square { list-style: square outside; }\n\tul.circle { list-style: circle outside; }\n\tul.disc { list-style: disc outside; }\n\tul ul, ul ol,\n\tol ol, ol ul { margin: 4px 0 5px 30px; font-size: 90%;  }\n\tul ul li, ul ol li,\n\tol ol li, ol ul li { margin-bottom: 6px; }\n\tli { line-height: 18px; margin-bottom: 12px; }\n\tul.large li { line-height: 21px; }\n\tli p { line-height: 21px; }\n\n/* #Images\n================================================== */\n\n\timg.scale-with-grid {\n\t\tmax-width: 100%;\n\t\theight: auto; }\n\n\n/* #Buttons\n================================================== */\n\n\ta.button,\n\tbutton,\n\tinput[type=\"submit\"],\n\tinput[type=\"reset\"],\n\tinput[type=\"button\"] {\n\t\tbackground: #eee; /* Old browsers */\n\t\tbackground: -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */\n\t\tbackground: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */\n\t\tbackground: -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */\n\t\tbackground: -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */\n\t\tbackground: -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */\n\t\tbackground: linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */\n\t  border: 1px solid #aaa;\n\t  border-top: 1px solid #ccc;\n\t  border-left: 1px solid #ccc;\n\t  padding: 4px 12px;\n\t  -moz-border-radius: 3px;\n\t  -webkit-border-radius: 3px;\n\t  border-radius: 3px;\n\t  color: #444;\n\t  display: inline-block;\n\t  font-size: 11px;\n\t  font-weight: bold;\n\t  text-decoration: none;\n\t  text-shadow: 0 1px rgba(255, 255, 255, .75);\n\t  cursor: pointer;\n\t  margin-bottom: 20px;\n\t  line-height: 21px;\n\t  font-family: \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif; }\n\n\ta.button:hover,\n\tbutton:hover,\n\tinput[type=\"submit\"]:hover,\n\tinput[type=\"reset\"]:hover,\n\tinput[type=\"button\"]:hover {\n\t\tcolor: #222;\n\t\tbackground: #ddd; /* Old browsers */\n\t\tbackground: -moz-linear-gradient(top, rgba(255,255,255,.3) 0%, rgba(0,0,0,.3) 100%); /* FF3.6+ */\n\t\tbackground: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.3)), color-stop(100%,rgba(0,0,0,.3))); /* Chrome,Safari4+ */\n\t\tbackground: -webkit-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Chrome10+,Safari5.1+ */\n\t\tbackground: -o-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Opera11.10+ */\n\t\tbackground: -ms-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* IE10+ */\n\t\tbackground: linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* W3C */\n\t  border: 1px solid #888;\n\t  border-top: 1px solid #aaa;\n\t  border-left: 1px solid #aaa; }\n\n  a.button:active,\n  button:active,\n\tinput[type=\"submit\"]:active,\n\tinput[type=\"reset\"]:active,\n\tinput[type=\"button\"]:active {\n\t\tborder: 1px solid #666;\n\t\tbackground: #ccc; /* Old browsers */\n\t\tbackground: -moz-linear-gradient(top, rgba(255,255,255,.35) 0%, rgba(10,10,10,.4) 100%); /* FF3.6+ */\n\t\tbackground: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.35)), color-stop(100%,rgba(10,10,10,.4))); /* Chrome,Safari4+ */\n\t\tbackground: -webkit-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Chrome10+,Safari5.1+ */\n\t\tbackground: -o-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Opera11.10+ */\n\t\tbackground: -ms-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* IE10+ */\n\t\tbackground: linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* W3C */ }\n\n\t.button.full-width,\n\tbutton.full-width,\n\tinput[type=\"submit\"].full-width,\n\tinput[type=\"reset\"].full-width,\n\tinput[type=\"button\"].full-width {\n\t\twidth: 100%;\n\t\tpadding-left: 0 !important;\n\t\tpadding-right: 0 !important;\n\t\ttext-align: center; }\n\n\n/* #Tabs (activate in tabs.js)\n================================================== */\n\tul.tabs {\n\t\tdisplay: block;\n\t\tmargin: 0 0 20px 0;\n\t\tpadding: 0;\n\t\tborder-bottom: solid 1px #ddd; }\n\tul.tabs li {\n\t\tdisplay: block;\n\t\twidth: auto;\n\t\theight: 30px;\n\t\tpadding: 0;\n\t\tfloat: left;\n\t\tmargin-bottom: 0; }\n\tul.tabs li a {\n\t\tdisplay: block;\n\t\ttext-decoration: none;\n\t\twidth: auto;\n\t\theight: 29px;\n\t\tpadding: 0px 20px;\n\t\tline-height: 30px;\n\t\tborder: solid 1px #ddd;\n\t\tborder-width: 1px 1px 0 0;\n\t\tmargin: 0;\n\t\tbackground: #f5f5f5;\n\t\tfont-size: 13px; }\n\tul.tabs li a.active {\n\t\tbackground: #fff;\n\t\theight: 30px;\n\t\tposition: relative;\n\t\ttop: -4px;\n\t\tpadding-top: 4px;\n\t\tborder-left-width: 1px;\n\t\tmargin: 0 0 0 -1px;\n\t\tcolor: #111;\n\t\t-moz-border-radius-topleft: 2px;\n\t\t-webkit-border-top-left-radius: 2px;\n\t\tborder-top-left-radius: 2px;\n\t\t-moz-border-radius-topright: 2px;\n\t\t-webkit-border-top-right-radius: 2px;\n\t\tborder-top-right-radius: 2px; }\n\tul.tabs li:first-child a.active {\n\t\tmargin-left: 0; }\n\tul.tabs li:first-child a {\n\t\tborder-width: 1px 1px 0 1px;\n\t\t-moz-border-radius-topleft: 2px;\n\t\t-webkit-border-top-left-radius: 2px;\n\t\tborder-top-left-radius: 2px; }\n\tul.tabs li:last-child a {\n\t\t-moz-border-radius-topright: 2px;\n\t\t-webkit-border-top-right-radius: 2px;\n\t\tborder-top-right-radius: 2px; }\n\n\tul.tabs-content { margin: 0; display: block; }\n\tul.tabs-content > li { display:none; }\n\tul.tabs-content > li.active { display: block; }\n\n\t/* Clearfixing tabs for beautiful stacking */\n\tul.tabs:before,\n\tul.tabs:after {\n\t  content: '\\0020';\n\t  display: block;\n\t  overflow: hidden;\n\t  visibility: hidden;\n\t  width: 0;\n\t  height: 0; }\n\tul.tabs:after {\n\t  clear: both; }\n\tul.tabs {\n\t  zoom: 1; }\n\n\n/* #Forms\n================================================== */\n\n\tform {\n\t\tmargin-bottom: 20px; }\n\tfieldset {\n\t\tmargin-bottom: 20px; }\n\tinput[type=\"text\"],\n\tinput[type=\"password\"],\n\tinput[type=\"email\"],\n\ttextarea,\n\tselect {\n\t\tborder: 1px solid #ccc;\n\t\tpadding: 6px 4px;\n\t\toutline: none;\n\t\t-moz-border-radius: 2px;\n\t\t-webkit-border-radius: 2px;\n\t\tborder-radius: 2px;\n\t\tfont: 13px \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n\t\tcolor: #777;\n\t\tmargin: 0;\n\t\twidth: 210px;\n\t\tmax-width: 100%;\n\t\tdisplay: block;\n\t\tmargin-bottom: 20px;\n\t\tbackground: #fff; }\n\tselect {\n\t\tpadding: 0; }\n\tinput[type=\"text\"]:focus,\n\tinput[type=\"password\"]:focus,\n\tinput[type=\"email\"]:focus,\n\ttextarea:focus {\n\t\tborder: 1px solid #aaa;\n \t\tcolor: #444;\n \t\t-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);\n\t\t-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);\n\t\tbox-shadow:  0 0 3px rgba(0,0,0,.2); }\n\ttextarea {\n\t\tmin-height: 60px; }\n\tlabel,\n\tlegend {\n\t\tdisplay: block;\n\t\tfont-weight: bold;\n\t\tfont-size: 13px;  }\n\tselect {\n\t\twidth: 220px; }\n\tinput[type=\"checkbox\"] {\n\t\tdisplay: inline; }\n\tlabel span,\n\tlegend span {\n\t\tfont-weight: normal;\n\t\tfont-size: 13px;\n\t\tcolor: #444; }\n\n/* #Misc\n================================================== */\n\t.remove-bottom { margin-bottom: 0 !important; }\n\t.half-bottom { margin-bottom: 10px !important; }\n\t.add-bottom { margin-bottom: 20px !important; }\n\n\n"
  },
  {
    "path": "doc/assets/css/skeleton/stylesheets/layout.css",
    "content": "/*\n* Skeleton V1.1\n* Copyright 2011, Dave Gamache\n* www.getskeleton.com\n* Free to use under the MIT license.\n* http://www.opensource.org/licenses/mit-license.php\n* 8/17/2011\n*/\n\n/* Table of Content\n==================================================\n\t#Site Styles\n\t#Page Styles\n\t#Media Queries\n\t#Font-Face */\n\n/* #Site Styles\n================================================== */\n\n/* #Page Styles\n================================================== */\n\n/* #Media Queries\n================================================== */\n\n\t/* Smaller than standard 960 (devices and browsers) */\n\t@media only screen and (max-width: 959px) {}\n\n\t/* Tablet Portrait size to standard 960 (devices and browsers) */\n\t@media only screen and (min-width: 768px) and (max-width: 959px) {}\n\n\t/* All Mobile Sizes (devices and browser) */\n\t@media only screen and (max-width: 767px) {}\n\n\t/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */\n\t@media only screen and (min-width: 480px) and (max-width: 767px) {}\n\n\t/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */\n\t@media only screen and (max-width: 479px) {}\n\n\n/* #Font-Face\n================================================== */\n/* \tThis is the proper syntax for an @font-face file\n\t\tJust create a \"fonts\" folder at the root,\n\t\tcopy your FontName into code below and remove\n\t\tcomment brackets */\n\n/*\t@font-face {\n\t    font-family: 'FontName';\n\t    src: url('../fonts/FontName.eot');\n\t    src: url('../fonts/FontName.eot?iefix') format('eot'),\n\t         url('../fonts/FontName.woff') format('woff'),\n\t         url('../fonts/FontName.ttf') format('truetype'),\n\t         url('../fonts/FontName.svg#webfontZam02nTh') format('svg');\n\t    font-weight: normal;\n\t    font-style: normal; }\n*/"
  },
  {
    "path": "doc/assets/css/skeleton/stylesheets/skeleton.css",
    "content": "/*\n* Skeleton V1.1\n* Copyright 2011, Dave Gamache\n* www.getskeleton.com\n* Free to use under the MIT license.\n* http://www.opensource.org/licenses/mit-license.php\n* 8/17/2011\n*/\n\n\n/* Table of Contents\n==================================================\n    #Base 960 Grid\n    #Tablet (Portrait)\n    #Mobile (Portrait)\n    #Mobile (Landscape)\n    #Clearing */\n\n\n\n/* #Base 960 Grid\n================================================== */\n\n    .container                                  { position: relative; width: 960px; margin: 0 auto; padding: 0; }\n    .column, .columns                           { float: left; display: inline; margin-left: 10px; margin-right: 10px; }\n    .row                                        { margin-bottom: 20px; }\n\n    /* Nested Column Classes */\n    .column.alpha, .columns.alpha               { margin-left: 0; }\n    .column.omega, .columns.omega               { margin-right: 0; }\n\n    /* Base Grid */\n    .container .one.column                      { width: 40px;  }\n    .container .two.columns                     { width: 100px; }\n    .container .three.columns                   { width: 160px; }\n    .container .four.columns                    { width: 220px; }\n    .container .five.columns                    { width: 280px; }\n    .container .six.columns                     { width: 340px; }\n    .container .seven.columns                   { width: 400px; }\n    .container .eight.columns                   { width: 460px; }\n    .container .nine.columns                    { width: 520px; }\n    .container .ten.columns                     { width: 580px; }\n    .container .eleven.columns                  { width: 640px; }\n    .container .twelve.columns                  { width: 700px; }\n    .container .thirteen.columns                { width: 760px; }\n    .container .fourteen.columns                { width: 820px; }\n    .container .fifteen.columns                 { width: 880px; }\n    .container .sixteen.columns                 { width: 940px; }\n\n    .container .one-third.column                { width: 300px; }\n    .container .two-thirds.column               { width: 620px; }\n\n    /* Offsets */\n    .container .offset-by-one                   { padding-left: 60px;  }\n    .container .offset-by-two                   { padding-left: 120px; }\n    .container .offset-by-three                 { padding-left: 180px; }\n    .container .offset-by-four                  { padding-left: 240px; }\n    .container .offset-by-five                  { padding-left: 300px; }\n    .container .offset-by-six                   { padding-left: 360px; }\n    .container .offset-by-seven                 { padding-left: 420px; }\n    .container .offset-by-eight                 { padding-left: 480px; }\n    .container .offset-by-nine                  { padding-left: 540px; }\n    .container .offset-by-ten                   { padding-left: 600px; }\n    .container .offset-by-eleven                { padding-left: 660px; }\n    .container .offset-by-twelve                { padding-left: 720px; }\n    .container .offset-by-thirteen              { padding-left: 780px; }\n    .container .offset-by-fourteen              { padding-left: 840px; }\n    .container .offset-by-fifteen               { padding-left: 900px; }\n\n\n\n/* #Tablet (Portrait)\n================================================== */\n\n    /* Note: Design for a width of 768px */\n\n    @media only screen and (min-width: 768px) and (max-width: 959px) {\n        .container                                  { width: 768px; }\n        .container .column,\n        .container .columns                         { margin-left: 10px; margin-right: 10px;  }\n        .column.alpha, .columns.alpha               { margin-left: 0; margin-right: 10px; }\n        .column.omega, .columns.omega               { margin-right: 0; margin-left: 10px; }\n\n        .container .one.column                      { width: 28px; }\n        .container .two.columns                     { width: 76px; }\n        .container .three.columns                   { width: 124px; }\n        .container .four.columns                    { width: 172px; }\n        .container .five.columns                    { width: 220px; }\n        .container .six.columns                     { width: 268px; }\n        .container .seven.columns                   { width: 316px; }\n        .container .eight.columns                   { width: 364px; }\n        .container .nine.columns                    { width: 412px; }\n        .container .ten.columns                     { width: 460px; }\n        .container .eleven.columns                  { width: 508px; }\n        .container .twelve.columns                  { width: 556px; }\n        .container .thirteen.columns                { width: 604px; }\n        .container .fourteen.columns                { width: 652px; }\n        .container .fifteen.columns                 { width: 700px; }\n        .container .sixteen.columns                 { width: 748px; }\n\n        .container .one-third.column                { width: 236px; }\n        .container .two-thirds.column               { width: 492px; }\n\n        /* Offsets */\n        .container .offset-by-one                   { padding-left: 48px; }\n        .container .offset-by-two                   { padding-left: 96px; }\n        .container .offset-by-three                 { padding-left: 144px; }\n        .container .offset-by-four                  { padding-left: 192px; }\n        .container .offset-by-five                  { padding-left: 240px; }\n        .container .offset-by-six                   { padding-left: 288px; }\n        .container .offset-by-seven                 { padding-left: 336px; }\n        .container .offset-by-eight                 { padding-left: 348px; }\n        .container .offset-by-nine                  { padding-left: 432px; }\n        .container .offset-by-ten                   { padding-left: 480px; }\n        .container .offset-by-eleven                { padding-left: 528px; }\n        .container .offset-by-twelve                { padding-left: 576px; }\n        .container .offset-by-thirteen              { padding-left: 624px; }\n        .container .offset-by-fourteen              { padding-left: 672px; }\n        .container .offset-by-fifteen               { padding-left: 720px; }\n    }\n\n\n/*  #Mobile (Portrait)\n================================================== */\n\n    /* Note: Design for a width of 320px */\n\n    @media only screen and (max-width: 767px) {\n        .container { width: 300px; }\n        .columns, .column { margin: 0; }\n\n        .container .one.column,\n        .container .two.columns,\n        .container .three.columns,\n        .container .four.columns,\n        .container .five.columns,\n        .container .six.columns,\n        .container .seven.columns,\n        .container .eight.columns,\n        .container .nine.columns,\n        .container .ten.columns,\n        .container .eleven.columns,\n        .container .twelve.columns,\n        .container .thirteen.columns,\n        .container .fourteen.columns,\n        .container .fifteen.columns,\n        .container .sixteen.columns,\n        .container .one-third.column,\n        .container .two-thirds.column  { width: 300px; }\n\n        /* Offsets */\n        .container .offset-by-one,\n        .container .offset-by-two,\n        .container .offset-by-three,\n        .container .offset-by-four,\n        .container .offset-by-five,\n        .container .offset-by-six,\n        .container .offset-by-seven,\n        .container .offset-by-eight,\n        .container .offset-by-nine,\n        .container .offset-by-ten,\n        .container .offset-by-eleven,\n        .container .offset-by-twelve,\n        .container .offset-by-thirteen,\n        .container .offset-by-fourteen,\n        .container .offset-by-fifteen { padding-left: 0; }\n\n    }\n\n\n/* #Mobile (Landscape)\n================================================== */\n\n    /* Note: Design for a width of 480px */\n\n    @media only screen and (min-width: 480px) and (max-width: 767px) {\n        .container { width: 420px; }\n        .columns, .column { margin: 0; }\n\n        .container .one.column,\n        .container .two.columns,\n        .container .three.columns,\n        .container .four.columns,\n        .container .five.columns,\n        .container .six.columns,\n        .container .seven.columns,\n        .container .eight.columns,\n        .container .nine.columns,\n        .container .ten.columns,\n        .container .eleven.columns,\n        .container .twelve.columns,\n        .container .thirteen.columns,\n        .container .fourteen.columns,\n        .container .fifteen.columns,\n        .container .sixteen.columns,\n        .container .one-third.column,\n        .container .two-thirds.column { width: 420px; }\n    }\n\n\n/* #Clearing\n================================================== */\n\n    /* Self Clearing Goodness */\n    .container:after { content: \"\\0020\"; display: block; height: 0; clear: both; visibility: hidden; }\n\n    /* Use clearfix class on parent to clear nested columns,\n    or wrap each row of columns in a <div class=\"row\"> */\n    .clearfix:before,\n    .clearfix:after,\n    .row:before,\n    .row:after {\n      content: '\\0020';\n      display: block;\n      overflow: hidden;\n      visibility: hidden;\n      width: 0;\n      height: 0; }\n    .row:after,\n    .clearfix:after {\n      clear: both; }\n    .row,\n    .clearfix {\n      zoom: 1; }\n\n    /* You can also use a <br class=\"clear\" /> to clear columns */\n    .clear {\n      clear: both;\n      display: block;\n      overflow: hidden;\n      visibility: hidden;\n      width: 0;\n      height: 0;\n    }\n\n\n"
  },
  {
    "path": "doc/assets/css/style.css",
    "content": "/**\n * A clean concise theme for your GitHub projects\n *\n * Licenced under GPL v3\n * http://www.gnu.org/licenses/gpl.html\n **/\n\n/* Page */\nbody {\n    background: #333333 url('../images/page-background.png') repeat top left;\n    font-family: arial,sans-serif;\n}\n\n/* Header */\nheader {\n    padding-top: 50px;\n    padding-bottom: 28px;\n}\n\n/* Footer */\nfooter {\n    background-color: #FFFFFF;\n    margin-top: 50px;\n    -webkit-box-shadow: -10px 0 15px #000000;\n    -moz-box-shadow: -10px 0 15px #000000;\n    box-shadow: -10px 0 15px #000000;\n}\n\ndiv.credits {\n    padding-top: 9px;\n    margin-top: 30px;\n    margin-bottom: 25px;\n    border-top: 1px solid #DDD2B2;\n    text-align: center;\n}\n\nfooter p table {\n    color: #333333;\n}\n\ndiv.repo-author {\n    padding-top: 30px;\n}\n\n/* Text */\np, strong, li {\n    color: #CCCCCC;\n    font-size: 14px;\n}\n\nstrong {\n    font-weight: bold;\n    color: #EEEEEE;\n}\n\na {\n    color: #0075B6;\n    text-decoration: none;\n}\n\na:visited {\n    color: #0075B6;\n}\n\na:hover {\n    text-decoration: underline;\n}\n\nh1, h2 {\n    font-family: georgia,serif;\n}\n\nh1 {\n    font-style: italic;\n    color: #FFFFFF;\n    font-size: 50px;\n    margin: 0;\n}\n\nh2 {\n    color: #CCCCCC;\n    font-size: 25px;\n    line-height: 23px;\n    padding-top: 15px;\n}\n\nh3, h4, h5 {\n    color: #FFFFFF;\n    font-weight: bold;\n    font-family: inherit;\n}\n\n\n/* Useful classes and styles */\na.github-ribbon {\n    position: absolute;\n    top: 0;\n    left: 0;\n    border: 0;\n}\n\na.download-button {\n    display: block;\n    padding: 15px 20px 10px 20px;\n    color: #FFFFFF;\n    text-decoration: none;\n    font-size: 28px;\n    font-weight: bold;\n    background: #33A700 url('../images/github-logo.png') no-repeat 92% 50%;\n    border: 2px solid #339410;\n    -webkit-box-shadow: 3px 3px 5px #000000;\n    -moz-box-shadow: 3px 3px 5px #000000;\n    box-shadow: 3px 3px 5px #000000;\n    -webkit-border-radius: 5px;\n    -moz-border-radius: 5px;\n    border-radius: 5px;\n    -webkit-transition: 350ms;\n    -moz-transition: 350ms;\n    -o-transition: 350ms;\n    transition: 350ms;\n}\n\na.download-button:hover {\n    background-color: #267C00;\n    background-position: 90% 50%;\n}\n\na.download-button span {\n    font-size: 14px;\n    display: block;\n    margin-top: 2px;\n}\n\ndiv.highlight {\n    margin-top: 15px;\n    min-height: 220px;\n    border: 3px solid #FFFFFF;\n    background-color: #CCCC99;\n    display: block;\n    padding: 20px;\n    font-family: monospace;\n    -webkit-box-shadow: 3px 3px 5px #000000;\n    -moz-box-shadow: 3px 3px 5px #000000;\n    box-shadow: 3px 3px 5px #000000;\n    overflow-x: auto;\n}\n\ndl {\n    margin-top: 15px;\n    min-height: 220px;\n    border: 3px solid #FFFFFF;\n    background-color: #CCCC99;\n    display: block;\n    padding: 20px;\n    font-family: monospace;\n    -webkit-box-shadow: 3px 3px 5px #000000;\n    -moz-box-shadow: 3px 3px 5px #000000;\n    box-shadow: 3px 3px 5px #000000;\n    overflow-x: auto;\n}\ndt {\n    font-weight: bold\n}\n\n\ncode {\n    margin-top: 15px;\n    min-height: 50px;\n    border: 3px solid #FFFFFF;\n    background-color: #CCCC99;\n    display: block;\n    padding: 20px;\n    font-family: monospace;\n    -webkit-box-shadow: 3px 3px 5px #000000;\n    -moz-box-shadow: 3px 3px 5px #000000;\n    box-shadow: 3px 3px 5px #000000;\n    overflow-x: auto;\n}\n\npre.prettyprint {\n    border: 0;\n    padding: 0;\n    margin: 0;\n}\n\nimg.repo-author-logo {\n    float: left;\n    margin-right: 15px;\n}\n\n.menu {\n    width: 100%;\n    border-bottom: 2px solid #77746C;\n    border-top: 2px solid #77746C;\n    margin-bottom: 28px;\n}\n\n.menu ul {\n    margin: 0;\n    padding: 0;\n    float: left;\n}\n\n.menu ul li {\n    display: inline;\n}\n\n.menu ul li a {\n    float: left;\n    text-decoration: none;\n    color: white;\n    padding: 10.5px 11px;\n}\n\n.menu ul li a:visited {\n    color: white;\n}\n\n.menu ul li a:hover, .menu ul li .current {\n    color: #fff;\n    background-color:#0b75b2;\n}\n\n/* Media queries */\n/* Hide the ribbon when we are on a phone, screen is too small */\n@media only screen and (max-width: 479px) {\n    a.github-ribbon {\n        display: none;\n    }\n}\n"
  },
  {
    "path": "doc/assets/javascript/html5.js",
    "content": "// html5shiv @rem remysharp.com/html5-enabling-script\n// iepp v1.6.2 @jon_neal iecss.com/print-protector\n// Dual licensed under the MIT or GPL Version 2 licenses\n/*@cc_on(function(a,b){function r(a){var b=-1;while(++b<f)a.createElement(e[b])}if(!(!window.attachEvent||!b.createStyleSheet||!function(){var a=document.createElement(\"div\");a.innerHTML=\"<elem></elem>\";return a.childNodes.length!==1}())){a.iepp=a.iepp||{};var c=a.iepp,d=c.html5elements||\"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",e=d.split(\"|\"),f=e.length,g=new RegExp(\"(^|\\\\s)(\"+d+\")\",\"gi\"),h=new RegExp(\"<(/*)(\"+d+\")\",\"gi\"),i=/^\\s*[\\{\\}]\\s*$/,j=new RegExp(\"(^|[^\\\\n]*?\\\\s)(\"+d+\")([^\\\\n]*)({[\\\\n\\\\w\\\\W]*?})\",\"gi\"),k=b.createDocumentFragment(),l=b.documentElement,m=l.firstChild,n=b.createElement(\"body\"),o=b.createElement(\"style\"),p=/print|all/,q;c.getCSS=function(a,b){if(a+\"\"===undefined)return\"\";var d=-1,e=a.length,f,g=[];while(++d<e){f=a[d];if(f.disabled)continue;b=f.media||b,p.test(b)&&g.push(c.getCSS(f.imports,b),f.cssText),b=\"all\"}return g.join(\"\")},c.parseCSS=function(a){var b=[],c;while((c=j.exec(a))!=null)b.push(((i.exec(c[1])?\"\\n\":c[1])+c[2]+c[3]).replace(g,\"$1.iepp_$2\")+c[4]);return b.join(\"\\n\")},c.writeHTML=function(){var a=-1;q=q||b.body;while(++a<f){var c=b.getElementsByTagName(e[a]),d=c.length,g=-1;while(++g<d)c[g].className.indexOf(\"iepp_\")<0&&(c[g].className+=\" iepp_\"+e[a])}k.appendChild(q),l.appendChild(n),n.className=q.className,n.id=q.id,n.innerHTML=q.innerHTML.replace(h,\"<$1font\")},c._beforePrint=function(){o.styleSheet.cssText=c.parseCSS(c.getCSS(b.styleSheets,\"all\")),c.writeHTML()},c.restoreHTML=function(){n.innerHTML=\"\",l.removeChild(n),l.appendChild(q)},c._afterPrint=function(){c.restoreHTML(),o.styleSheet.cssText=\"\"},r(b),r(k);if(c.disablePP)return;m.insertBefore(o,m.firstChild),o.media=\"print\",o.className=\"iepp-printshim\",a.attachEvent(\"onbeforeprint\",c._beforePrint),a.attachEvent(\"onafterprint\",c._afterPrint)}})(this,document);@*/\n"
  },
  {
    "path": "doc/assets/javascript/lang-apollo.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"com\",/^#[^\\n\\r]*/,null,\"#\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,null,'\"']],[[\"kwd\",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\\s/,\nnull],[\"typ\",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\\*?|2?DEC\\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\\s/,null],[\"lit\",/^'(?:-*(?:\\w|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?)?/],[\"pln\",/^-*(?:[!-z]|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?/],[\"pun\",/^[^\\w\\t\\n\\r \"'-);\\\\\\xa0]+/]]),[\"apollo\",\"agc\",\"aea\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-clj.js",
    "content": "/*\n Copyright (C) 2011 Google Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\nvar a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"opn\",/^[([{]+/,a,\"([{\"],[\"clo\",/^[)\\]}]+/,a,\")]}\"],[\"com\",/^;[^\\n\\r]*/,a,\";\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,a,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,a,'\"']],[[\"kwd\",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\\b/,a],\n[\"typ\",/^:[\\dA-Za-z-]+/]]),[\"clj\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-css.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\f\\r ]+/,null,\" \\t\\r\\n\f\"]],[[\"str\",/^\"(?:[^\\n\\f\\r\"\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*\"/,null],[\"str\",/^'(?:[^\\n\\f\\r'\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*'/,null],[\"lang-css-str\",/^url\\(([^\"')]*)\\)/i],[\"kwd\",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\\w-]|$)/i,null],[\"lang-css-kw\",/^(-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*)\\s*:/i],[\"com\",/^\\/\\*[^*]*\\*+(?:[^*/][^*]*\\*+)*\\//],[\"com\",\n/^(?:<\\!--|--\\>)/],[\"lit\",/^(?:\\d+|\\d*\\.\\d+)(?:%|[a-z]+)?/i],[\"lit\",/^#[\\da-f]{3,6}/i],[\"pln\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i],[\"pun\",/^[^\\s\\w\"']+/]]),[\"css\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"kwd\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i]]),[\"css-kw\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"str\",/^[^\"')]+/]]),[\"css-str\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-go.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"pln\",/^(?:\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])+(?:'|$)|`[^`]*(?:`|$))/,null,\"\\\"'\"]],[[\"com\",/^(?:\\/\\/[^\\n\\r]*|\\/\\*[\\S\\s]*?\\*\\/)/],[\"pln\",/^(?:[^\"'/`]|\\/(?![*/]))+/]]),[\"go\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-hs.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t-\\r ]+/,null,\"\\t\\n\u000b\f\\r \"],[\"str\",/^\"(?:[^\\n\\f\\r\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,null,'\"'],[\"str\",/^'(?:[^\\n\\f\\r'\\\\]|\\\\[^&])'?/,null,\"'\"],[\"lit\",/^(?:0o[0-7]+|0x[\\da-f]+|\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?)/i,null,\"0123456789\"]],[[\"com\",/^(?:--+[^\\n\\f\\r]*|{-(?:[^-]|-+[^}-])*-})/],[\"kwd\",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\\d'A-Za-z]|$)/,\nnull],[\"pln\",/^(?:[A-Z][\\w']*\\.)*[A-Za-z][\\w']*/],[\"pun\",/^[^\\d\\t-\\r \"'A-Za-z]+/]]),[\"hs\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-lisp.js",
    "content": "var a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"opn\",/^\\(+/,a,\"(\"],[\"clo\",/^\\)+/,a,\")\"],[\"com\",/^;[^\\n\\r]*/,a,\";\"],[\"pln\",/^[\\t\\n\\r \\xa0]+/,a,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)/,a,'\"']],[[\"kwd\",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\\b/,a],\n[\"lit\",/^[+-]?(?:[#0]x[\\da-f]+|\\d+\\/\\d+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:[de][+-]?\\d+)?)/i],[\"lit\",/^'(?:-*(?:\\w|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?)?/],[\"pln\",/^-*(?:[_a-z]|\\\\[!-~])(?:[\\w-]*|\\\\[!-~])[!=?]?/i],[\"pun\",/^[^\\w\\t\\n\\r \"'-);\\\\\\xa0]+/]]),[\"cl\",\"el\",\"lisp\",\"scm\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-lua.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^(?:\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$))/,null,\"\\\"'\"]],[[\"com\",/^--(?:\\[(=*)\\[[\\S\\s]*?(?:]\\1]|$)|[^\\n\\r]*)/],[\"str\",/^\\[(=*)\\[[\\S\\s]*?(?:]\\1]|$)/],[\"kwd\",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b/,null],[\"lit\",/^[+-]?(?:0x[\\da-f]+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:e[+-]?\\d+)?)/i],\n[\"pln\",/^[_a-z]\\w*/i],[\"pun\",/^[^\\w\\t\\n\\r \\xa0][^\\w\\t\\n\\r \"'+=\\xa0-]*/]]),[\"lua\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-ml.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"com\",/^#(?:if[\\t\\n\\r \\xa0]+(?:[$_a-z][\\w']*|``[^\\t\\n\\r`]*(?:``|$))|else|endif|light)/i,null,\"#\"],[\"str\",/^(?:\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])(?:'|$))/,null,\"\\\"'\"]],[[\"com\",/^(?:\\/\\/[^\\n\\r]*|\\(\\*[\\S\\s]*?\\*\\))/],[\"kwd\",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\\b/],\n[\"lit\",/^[+-]?(?:0x[\\da-f]+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:e[+-]?\\d+)?)/i],[\"pln\",/^(?:[_a-z][\\w']*[!#?]?|``[^\\t\\n\\r`]*(?:``|$))/i],[\"pun\",/^[^\\w\\t\\n\\r \"'\\xa0]+/]]),[\"fs\",\"ml\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-n.js",
    "content": "var a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*'|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,a,'\"'],[\"com\",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,a,\"#\"],[\"pln\",/^\\s+/,a,\" \\r\\n\\t\\xa0\"]],[[\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,a],[\"str\",/^<#[^#>]*(?:#>|$)/,a],[\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>/,a],[\"com\",/^\\/\\/[^\\n\\r]*/,a],[\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,\na],[\"kwd\",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\\b/,\na],[\"typ\",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\\b/,a],[\"lit\",/^@[$_a-z][\\w$@]*/i,a],[\"typ\",/^@[A-Z]+[a-z][\\w$@]*/,a],[\"pln\",/^'?[$_a-z][\\w$@]*/i,a],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,a,\"0123456789\"],[\"pun\",/^.[^\\s\\w\"-$'./@`]*/,a]]),[\"n\",\"nemerle\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-proto.js",
    "content": "PR.registerLangHandler(PR.sourceDecorator({keywords:\"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true\",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\\b/,cStyleComments:!0}),[\"proto\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-scala.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^\"(?:\"\"(?:\"\"?(?!\")|[^\"\\\\]|\\\\.)*\"{0,3}|(?:[^\\n\\r\"\\\\]|\\\\.)*\"?)/,null,'\"'],[\"lit\",/^`(?:[^\\n\\r\\\\`]|\\\\.)*`?/,null,\"`\"],[\"pun\",/^[!#%&(--:-@[-^{-~]+/,null,\"!#%&()*+,-:;<=>?@[\\\\]^{|}~\"]],[[\"str\",/^'(?:[^\\n\\r'\\\\]|\\\\(?:'|[^\\n\\r']+))'/],[\"lit\",/^'[$A-Z_a-z][\\w$]*(?![\\w$'])/],[\"kwd\",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\\b/],\n[\"lit\",/^(?:true|false|null|this)\\b/],[\"lit\",/^(?:0(?:[0-7]+|x[\\da-f]+)l?|(?:0|[1-9]\\d*)(?:(?:\\.\\d+)?(?:e[+-]?\\d+)?f?|l?)|\\\\.\\d+(?:e[+-]?\\d+)?f?)/i],[\"typ\",/^[$_]*[A-Z][\\d$A-Z_]*[a-z][\\w$]*/],[\"pln\",/^[$A-Z_a-z][\\w$]*/],[\"com\",/^\\/(?:\\/.*|\\*(?:\\/|\\**[^*/])*(?:\\*+\\/?)?)/],[\"pun\",/^(?:\\.+|\\/)/]]),[\"scala\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-sql.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"str\",/^(?:\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')/,null,\"\\\"'\"]],[[\"com\",/^(?:--[^\\n\\r]*|\\/\\*[\\S\\s]*?(?:\\*\\/|$))/],[\"kwd\",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\\w-]|$)/i,\nnull],[\"lit\",/^[+-]?(?:0x[\\da-f]+|(?:\\.\\d+|\\d+(?:\\.\\d*)?)(?:e[+-]?\\d+)?)/i],[\"pln\",/^[_a-z][\\w-]*/i],[\"pun\",/^[^\\w\\t\\n\\r \"'\\xa0][^\\w\\t\\n\\r \"'+\\xa0-]*/]]),[\"sql\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-tex.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"],[\"com\",/^%[^\\n\\r]*/,null,\"%\"]],[[\"kwd\",/^\\\\[@-Za-z]+/],[\"kwd\",/^\\\\./],[\"typ\",/^[$&]/],[\"lit\",/[+-]?(?:\\.\\d+|\\d+(?:\\.\\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],[\"pun\",/^[()=[\\]{}]+/]]),[\"latex\",\"tex\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-vb.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0\\u2028\\u2029]+/,null,\"\\t\\n\\r \\xa0  \"],[\"str\",/^(?:[\"\\u201c\\u201d](?:[^\"\\u201c\\u201d]|[\"\\u201c\\u201d]{2})(?:[\"\\u201c\\u201d]c|$)|[\"\\u201c\\u201d](?:[^\"\\u201c\\u201d]|[\"\\u201c\\u201d]{2})*(?:[\"\\u201c\\u201d]|$))/i,null,'\"“”'],[\"com\",/^['\\u2018\\u2019].*/,null,\"'‘’\"]],[[\"kwd\",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\\b/i,\nnull],[\"com\",/^rem.*/i],[\"lit\",/^(?:true\\b|false\\b|nothing\\b|\\d+(?:e[+-]?\\d+[dfr]?|[dfilrs])?|(?:&h[\\da-f]+|&o[0-7]+)[ils]?|\\d*\\.\\d+(?:e[+-]?\\d+)?[dfr]?|#\\s+(?:\\d+[/-]\\d+[/-]\\d+(?:\\s+\\d+:\\d+(?::\\d+)?(\\s*(?:am|pm))?)?|\\d+:\\d+(?::\\d+)?(\\s*(?:am|pm))?)\\s+#)/i],[\"pln\",/^(?:(?:[a-z]|_\\w)\\w*|\\[(?:[a-z]|_\\w)\\w*])/i],[\"pun\",/^[^\\w\\t\\n\\r \"'[\\]\\xa0\\u2018\\u2019\\u201c\\u201d\\u2028\\u2029]+/],[\"pun\",/^(?:\\[|])/]]),[\"vb\",\"vbs\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-vhdl.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\r \\xa0]+/,null,\"\\t\\n\\r \\xa0\"]],[[\"str\",/^(?:[box]?\"(?:[^\"]|\"\")*\"|'.')/i],[\"com\",/^--[^\\n\\r]*/],[\"kwd\",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\\w-]|$)/i,\nnull],[\"typ\",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\\w-]|$)/i,null],[\"typ\",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\\w-]|$)/i,null],[\"lit\",/^\\d+(?:_\\d+)*(?:#[\\w.\\\\]+#(?:[+-]?\\d+(?:_\\d+)*)?|(?:\\.\\d+(?:_\\d+)*)?(?:e[+-]?\\d+(?:_\\d+)*)?)/i],\n[\"pln\",/^(?:[a-z]\\w*|\\\\[^\\\\]*\\\\)/i],[\"pun\",/^[^\\w\\t\\n\\r \"'\\xa0][^\\w\\t\\n\\r \"'\\xa0-]*/]]),[\"vhdl\",\"vhd\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-wiki.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\d\\t a-gi-z\\xa0]+/,null,\"\\t \\xa0abcdefgijklmnopqrstuvwxyz0123456789\"],[\"pun\",/^[*=[\\]^~]+/,null,\"=*~^[]\"]],[[\"lang-wiki.meta\",/(?:^^|\\r\\n?|\\n)(#[a-z]+)\\b/],[\"lit\",/^[A-Z][a-z][\\da-z]+[A-Z][a-z][^\\W_]+\\b/],[\"lang-\",/^{{{([\\S\\s]+?)}}}/],[\"lang-\",/^`([^\\n\\r`]+)`/],[\"str\",/^https?:\\/\\/[^\\s#/?]*(?:\\/[^\\s#?]*)?(?:\\?[^\\s#]*)?(?:#\\S*)?/i],[\"pln\",/^(?:\\r\\n|[\\S\\s])[^\\n\\r#*=A-[^`h{~]*/]]),[\"wiki\"]);\nPR.registerLangHandler(PR.createSimpleLexer([[\"kwd\",/^#[a-z]+/i,null,\"#\"]],[]),[\"wiki.meta\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-xq.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"var pln\",/^\\$[\\w-]+/,null,\"$\"]],[[\"pln\",/^[\\s=][<>][\\s=]/],[\"lit\",/^@[\\w-]+/],[\"tag\",/^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"com\",/^\\(:[\\S\\s]*?:\\)/],[\"pln\",/^[(),/;[\\]{}]$/],[\"str\",/^(?:\"(?:[^\"\\\\{]|\\\\[\\S\\s])*(?:\"|$)|'(?:[^'\\\\{]|\\\\[\\S\\s])*(?:'|$))/,null,\"\\\"'\"],[\"kwd\",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\\b/],\n[\"typ\",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\\b/,null],[\"fun pln\",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\\b/],\n[\"pln\",/^[\\w:-]+/],[\"pln\",/^[\\t\\n\\r \\xa0]+/]]),[\"xq\",\"xquery\"]);\n"
  },
  {
    "path": "doc/assets/javascript/lang-yaml.js",
    "content": "var a=null;\nPR.registerLangHandler(PR.createSimpleLexer([[\"pun\",/^[:>?|]+/,a,\":|>?\"],[\"dec\",/^%(?:YAML|TAG)[^\\n\\r#]+/,a,\"%\"],[\"typ\",/^&\\S+/,a,\"&\"],[\"typ\",/^!\\S*/,a,\"!\"],[\"str\",/^\"(?:[^\"\\\\]|\\\\.)*(?:\"|$)/,a,'\"'],[\"str\",/^'(?:[^']|'')*(?:'|$)/,a,\"'\"],[\"com\",/^#[^\\n\\r]*/,a,\"#\"],[\"pln\",/^\\s+/,a,\" \\t\\r\\n\"]],[[\"dec\",/^(?:---|\\.\\.\\.)(?:[\\n\\r]|$)/],[\"pun\",/^-/],[\"kwd\",/^\\w+:[\\n\\r ]/],[\"pln\",/^\\w+/]]),[\"yaml\",\"yml\"]);\n"
  },
  {
    "path": "doc/assets/javascript/prettify.js",
    "content": "var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;\n(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:\"0\"<=b&&b<=\"7\"?parseInt(a.substring(1),8):b===\"u\"||b===\"x\"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?\"\\\\x0\":\"\\\\x\")+a.toString(16);a=String.fromCharCode(a);if(a===\"\\\\\"||a===\"-\"||a===\"[\"||a===\"]\")a=\"\\\\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\S\\s]|[^\\\\]/g),a=\n[],b=[],o=f[0]===\"^\",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&\"-\"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=[\"[\"];o&&b.push(\"^\");b.push.apply(b,a);for(c=0;c<\nf.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push(\"-\"),b.push(e(i[1])));b.push(\"]\");return b.join(\"\")}function y(a){for(var f=a.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j===\"(\"?++i:\"\\\\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j===\"(\"?(++i,d[i]===void 0&&(f[c]=\"(?:\")):\"\\\\\"===j.charAt(0)&&\n(j=+j.substring(1))&&j<=i&&(f[c]=\"\\\\\"+d[i]);for(i=c=0;c<b;++c)\"^\"===f[c]&&\"^\"!==f[c+1]&&(f[c]=\"\");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a===\"[\"?f[c]=h(j):a!==\"\\\\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return f.join(\"\")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\\\u[\\da-f]{4}|\\\\x[\\da-f]{2}|\\\\[^UXux]/gi,\"\"))){s=!0;l=!1;break}}for(var r=\n{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(\"\"+g);n.push(\"(?:\"+y(g)+\")\")}return RegExp(n.join(\"|\"),l?\"gi\":\"g\")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if(\"BR\"===g||\"LI\"===g)h[s]=\"\\n\",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\\r\\n?/g,\"\\n\"):g.replace(/[\\t\\n\\r ]+/g,\" \"),h[s]=g,t[s<<1]=y,y+=g.length,\nt[s++<<1|1]=a)}}var e=/(?:^|\\s)nocode(?:\\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);m(a);return{a:h.join(\"\").replace(/\\n$/,\"\"),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,\"pln\"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===\n\"string\")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b=\"pln\")}if((c=b.length>=5&&\"lang-\"===b.substring(0,5))&&!(o&&typeof o[1]===\"string\"))c=!1,b=\"src\";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),\nl=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=\"\"+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\\S\\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push([\"str\",/^(?:'''(?:[^'\\\\]|\\\\[\\S\\s]|''?(?=[^']))*(?:'''|$)|\"\"\"(?:[^\"\\\\]|\\\\[\\S\\s]|\"\"?(?=[^\"]))*(?:\"\"\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$))/,q,\"'\\\"\"]):a.multiLineStrings?m.push([\"str\",/^(?:'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,\nq,\"'\\\"`\"]):m.push([\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*(?:'|$)|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,q,\"\\\"'\"]);a.verbatimStrings&&e.push([\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,\"#\"]):m.push([\"com\",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,q,\"#\"]),e.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>/,q])):m.push([\"com\",/^#[^\\n\\r]*/,\nq,\"#\"]));a.cStyleComments&&(e.push([\"com\",/^\\/\\/[^\\n\\r]*/,q]),e.push([\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,q]));a.regexLiterals&&e.push([\"lang-regex\",/^(?:^^\\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|,|-=|->|\\/|\\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\\^=|\\^\\^|\\^\\^=|{|\\||\\|=|\\|\\||\\|\\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*(\\/(?=[^*/])(?:[^/[\\\\]|\\\\[\\S\\s]|\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*(?:]|$))+\\/)/]);(h=a.types)&&e.push([\"typ\",h]);a=(\"\"+a.keywords).replace(/^ | $/g,\n\"\");a.length&&e.push([\"kwd\",RegExp(\"^(?:\"+a.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),q]);m.push([\"pln\",/^\\s+/,q,\" \\r\\n\\t\\xa0\"]);e.push([\"lit\",/^@[$_a-z][\\w$@]*/i,q],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,q],[\"pln\",/^[$_a-z][\\w$@]*/i,q],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,q,\"0123456789\"],[\"pln\",/^\\\\[\\S\\s]?/,q],[\"pun\",/^.[^\\s\\w\"-$'./@\\\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if(\"BR\"===a.nodeName)h(a),\na.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}\nfor(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\\s)nocode(?:\\s|$)/,t=/\\r\\n?|\\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);for(l=s.createElement(\"LI\");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute(\"value\",\nm);var r=s.createElement(\"OL\");r.className=\"linenums\";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className=\"L\"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode(\"\\xa0\")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn(\"cannot override language handler %s\",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\\s*</.test(m)?\"default-markup\":\"default-code\";return A[a]}function E(a){var m=\na.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\\bMSIE\\b/.test(navigator.userAgent),m=/\\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,\"\\r\"));i.nodeValue=\nj;var u=i.ownerDocument,v=u.createElement(\"SPAN\");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){\"console\"in window&&console.log(w&&w.stack?w.stack:w)}}var v=[\"break,continue,do,else,for,if,return,while\"],w=[[v,\"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\n\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],F=[w,\"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],G=[w,\"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient\"],\nH=[G,\"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var\"],w=[w,\"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN\"],I=[v,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],\nJ=[v,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],v=[v,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)/,N=/\\S/,O=u({keywords:[F,H,w,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\"+\nI,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,[\"default-code\"]);k(x([],[[\"pln\",/^[^<?]+/],[\"dec\",/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],[\"lang-\",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\S\\s]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",/^<xmp\\b[^>]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),\n[\"default-markup\",\"htm\",\"html\",\"mxml\",\"xhtml\",\"xml\",\"xsl\"]);k(x([[\"pln\",/^\\s+/,q,\" \\t\\r\\n\"],[\"atv\",/^(?:\"[^\"]*\"?|'[^']*'?)/,q,\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^\\s\"'>]*(?:[^\\s\"'/>]|\\/(?=\\s)))/],[\"pun\",/^[/<->]+/],[\"lang-js\",/^on\\w+\\s*=\\s*\"([^\"]+)\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*'([^']+)'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\s\"'>]+)/i],[\"lang-css\",/^style\\s*=\\s*\"([^\"]+)\"/i],[\"lang-css\",/^style\\s*=\\s*'([^']+)'/i],[\"lang-css\",\n/^style\\s*=\\s*([^\\s\"'>]+)/i]]),[\"in.tag\"]);k(x([],[[\"atv\",/^[\\S\\s]+/]]),[\"uq.val\"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),[\"c\",\"cc\",\"cpp\",\"cxx\",\"cyc\",\"m\"]);k(u({keywords:\"null,true,false\"}),[\"json\"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),[\"cs\"]);k(u({keywords:G,cStyleComments:!0}),[\"java\"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),[\"bsh\",\"csh\",\"sh\"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),\n[\"cv\",\"py\"]);k(u({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"perl\",\"pl\",\"pm\"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),[\"js\"]);k(u({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes\",\nhashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),[\"coffee\"]);k(x([],[[\"str\",/^[\\S\\s]+/]]),[\"regex\"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement(\"PRE\");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf(\"prettyprint\")>=0){var k=k.match(g),f,b;if(b=\n!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&\"CODE\"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName===\"pre\"||o.tagName===\"code\"||o.tagName===\"xmp\")&&o.className&&o.className.indexOf(\"prettyprint\")>=0){b=!0;break}b||((b=(b=n.className.match(/\\blinenums\\b(?::(\\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,\n250):a&&a()}for(var e=[document.getElementsByTagName(\"pre\"),document.getElementsByTagName(\"code\"),document.getElementsByTagName(\"xmp\")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",\nPR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\"}})();\n"
  },
  {
    "path": "doc/index.md",
    "content": "---\nlayout: default\ntitle: Swarm oriented ERlang Expert SYstem Engine\n---\n\nIntroduction\n------------\n\nSERESYE is a Rete based rules engine written in Erlang, descended\ndirectly from the Eresye project by Francesca Gangemi and Corrado\nSantoro. In the following article we will describe how to use the\nsystem.\n\nA rule-based system is composed of a **knowledge base**, which stores\na set of *facts* representing the 'universe of discourse' of a given\napplication, and a set of **production rules**, which are used to\ninfer knowledge and/or reason about the knowledge. A rule is activated\nwhen one or more facts match the template(s) given in the rule\ndeclaration: in such a case, the body of the rule contains a code that\nis thus executed\n\nIn SERESYE, *facts* are expressed by means of Erlang tuples or records,\nwhile rules are written using standard Erlang function clauses, whose\ndeclaration reports, in the clause head, the facts or fact templates\nthat have to be matched for the rule to be activated and executed.\n\nFor more information about SERESYE please refer to the paper docs directory.\n\nFor more information about rule-based inference engines and expert\nsystems, you can refer to the book: *S. Russell and\nP. Norvig. **Artificial Intelligence: A Modern Approach/2E.** Prentice\nHall, 2003.*\n\nTo write an AI application with SERESYE the following steps have to be\nperformed:\n\n1. Identify your universe of discourse and determine the facts that\n   have to be used to represent such a world;\n\n2. Identify the rules that you need and write them by using, e.g.\n   first-order-logic predicates or even natural language;\n\n3. Implement the system by writing your rules as Erlang function\n   clauses, according to the modality required by SERESYE.\n\n\nThe Application: the Domain of Relatives\n----------------------------------------\n\nWe will design a system able to derive new knowledge using some\ninference rules and starting from a small set; as a sample\napplication, we chose the domain of relatives: we will start from some\nbase concepts, such as *parent*, *male* and *female*, and then, by\nmeans of a proper set of rules, we will derive the concepts of\n*mother*, *father*, *sister*, *brother*, *grandmother* and\n*grandfather*.\n\nAccording to the list above, we will first derive the facts that will be\nused to represent our concepts. Given the set of relationships above, they\nwill be represented by means of the following facts:\n\n<table border=\"1\" align=\"center\">\n<thead>\n  <tr>\n    <td><p>#</p></td>\n    <td><p>Concept</p></td>\n    <td><p>Fact / Erlang tuple</p></td>\n  </tr>\n</thead>\n<tbody>\n  <tr>\n    <td><p>1</p></td>\n    <td><p>X is male</p></td>\n    <td><p><tt>{male, X}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>2</p></td>\n    <td><p>X is female</p></td>\n    <td><p><tt>{female, X}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>3</p></td>\n    <td><p>X is Y's parent</p></td>\n    <td><p><tt>{parent, X, Y}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>4</p></td>\n    <td><p>X is Y's mother</p></td>\n    <td><p><tt>{mother, X, Y}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>5</p></td>\n    <td><p>X is Y's father</p></td>\n    <td><p><tt>{father, X, Y}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>6</p></td>\n    <td><p>X is Y's sister</p></td>\n    <td><p><tt>{sister, X, Y}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>7</p></td>\n    <td><p>X is Y's brother</p></td>\n    <td><p><tt>{brother, X, Y}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>8</p></td>\n    <td><p>X is Y's grandmother</p></td>\n    <td><p><tt>{grandmother, X, Y}</tt></p></td>\n  </tr>\n  <tr>\n    <td><p>9</p></td>\n    <td><p>X is Y's grandfather</p></td>\n    <td><p><tt>{grandfather, X, Y}</tt></p></td>\n  </tr>\n</tbody>\n</table>\n\nConcepts 1, 2 and 3 will be used as a base to derive the other ones.\n\nDeriving new concepts by means of rules\n---------------------------------------\n\n#### Concept: mother\n\nThe rule to derive the concept of mother is quite\nstraightforward:\n\n    if X is female and X is Y's parent then X is Y's mother.\n\nFrom the point of view of SERESYE, since knowledge is stored in the\n*knowledge base* of the engine, the rule above is translated into the\nfollowing one: *if the facts {female, X} and {parent, X, Y} are\n*asserted* in the knowledge base, then we assert the fact {mother, X,\nY}.\n\nThe rule *mother* can be thus written as follows:\n\n    %%\n    %% if (X is female) and (X is Y's parent) then (X is Y's mother)\n    %%\n    mother (Engine, {female, X}, {parent, X, Y}) ->\n      seresye:assert (Engine, {mother, X, Y}).\n\n\n#### Concept: father\n\nThis concept can be easily derived by means of the following rule:\n\n    %%\n    %% if (X is male) and (X is Y's parent) then (X is Y's father)\n    %%\n    father (Engine, {male, X}, {parent, X, Y}) ->\n      seresye:assert (Engine, {father, X, Y}).\n\n\n#### Concept: sister\n\n This concept can be expressed by the following rule:\n\n    if Y and Z have the same parent and Z is female, then Z\n    is the Y's sister.\n\nThe SERESYE rule used to map this concept is:\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is female)\n    %%    then (Z is Y's sister)\n    %%\n    sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->\n      seresye:assert (Engine, {sister, Z, Y}).\n\n\nPlease note the guard, which is needed to ensure that when Y and Z are\nbound to the same value, the rule is not activated (indeed this is\npossible since the same fact can match both the first and second\n'parent' pattern).\n\n#### Concept: brother\n\nGiven the previous one, this concept is now quite simple to\nimplement:\n\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is male)\n    %%    then (Z is Y's brother)\n    %%\n    brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->\n      seresye:assert (Engine, {brother, Z, Y}).\n\n\n#### Concepts: grandmother and grandfather\n\nThe former concept can be expressed by means of the rule:\n\n    if X is Y's mother and Y is Z's parent, then X is Z's\n    grandmother.</u>* The latter concept is now obvious.\n\nBoth can be implemented using the following SERESYE rules:\n\n    %%\n    %% if (X is Y's mother) and (Y is Z's parent)\n    %%    then (X is Z's grandmother)\n    %%\n    grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) ->\n      seresye:assert (Engine, {grandmother, X, Z}).\n\n    %%\n    %% if (X is Y's father) and (Y is Z's parent)\n    %%    then (X is Z's grandfather)\n    %%\n    grandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->\n      seresye:assert (Engine, {grandfather, X, Z}).\n\n\nInstantiating the Engine and Populating the Knowledge Base\n----------------------------------------------------------\n\nAfter writing the rules, we need to:\n\n- define the rules to seresye\n- instantiate the engine;\n- populate the knowledge base with a set of initial facts.\n\nWe define the rules to SERESYE by defined a 'rules' attribute at the\nstart of the module.\n\n    %%%\n    %%% relatives.erl\n    %%%\n    -module (relatives).\n\n    -export([father/3, grandfather/3, grandmother/3,\n             mother/3, brother/4, sister/4, start/0]).\n\n    -rules([mother, father, brother, sister, grandfather,\n            grandmother]).\n\nWe continue on to instantiate the engine and popoulate the knowledge\nbase in the function *start* below:\n\n    start () ->\n      application:start(seresye) % Only if it is not already started\n      seresye:start(relatives),\n      seresye:add_rules(relatives, ?MODULE)\n\n      seresye:assert(relatives,\n                     [{male, bob}, {male, corrado}, {male, mark}, {male, caesar},\n                      {female, alice}, {female, sara}, {female, jane}, {female, anna},\n                      {parent, jane, bob}, {parent, corrado, bob},\n                      {parent, jane, mark}, {parent, corrado, mark},\n                      {parent, jane, alice}, {parent, corrado, alice},\n                      {parent, bob, caesar}, {parent, bob, anna},\n                      {parent, sara, casear}, {parent, sara, anna}]),\n      ok.\n\nAs the listing reports, creating a new SERESYE engine implies to call\nthe function *seresye:start/1*, giving the name of the engine to be\ncreated\n\nThen, we have to add the rules to the engine by using the function\n*seresye:add_rule/2*: it takes two arguments, the name of the engine\nand a tuple representing the function in the form *{Module,\nFuncName}*; obviously the function *Module:FuncName* must be\nexported. Function *add_rule* has to be called for each rule that has\nto be added; for this reason, the code above has an iteration over the\nlist of rules written before.\n\nFinally, we populate the inference engine with a set of sample facts\nby giving them, in a list, to the function *seresye:assert/2*.  To test\nour rules, we considered the relationships in the Figure below and\nassert only the facts for *male*, *female* and *parent*.\n\nTesting the application\n-----------------------\n\nThe final complete code of our AI application is thus the following:\n\n\n    %%%\n    %%% relatives.erl\n    %%%\n    -module (relatives).\n    -export([father/3, grandfather/3, grandmother/3,\n             mother/3, brother/4, sister/4, start/0]).\n\n    %%\n    %% if (X is female) and (X is Y's parent) then (X is Y's mother)\n    %%\n    mother(Engine, {female, X}, {parent, X, Y}) ->\n      seresye:assert(Engine, {mother, X, Y}).\n\n    %%\n    %% if (X is male) and (X is Y's parent) then (X is Y's father)\n    %%\n    father(Engine, {male, X}, {parent, X, Y}) ->\n      seresye:assert(Engine, {father, X, Y}).\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is female)\n    %%    then (Z is Y's sister)\n    %%\n    sister(Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->\n      seresye:assert(Engine, {sister, Z, Y}).\n\n    %%\n    %% if (Y and Z have the same parent X) and (Z is male)\n    %%    then (Z is Y's brother)\n    %%\n    brother(Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->\n      seresye:assert(Engine, {brother, Z, Y}).\n\n    %%\n    %% if (X is Y's father) and (Y is Z's parent)\n    %%    then (X is Z's grandfather)\n    %%\n    grandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->\n      seresye:assert (Engine, {grandfather, X, Z}).\n\n    %%\n    %% if (X is Y's mother) and (Y is Z's parent)\n    %%    then (X is Z's grandmother)\n    %%\n    grandmother(Engine, {mother, X, Y}, {parent, Y, Z}) ->\n      seresye:assert(Engine, {grandmother, X, Z}).\n\n    start () ->\n      application:start(seresye),\n      seresye:start (relatives),\n      seresye:add_rules(relatives, ?MODULE)\n\n      seresye:assert (relatives,\n                     [{male, bob},\n                      {male, corrado},\n                      {male, mark},\n                      {male, caesar},\n                      {female, alice},\n                      {female, sara},\n                      {female, jane},\n                      {female, anna},\n                      {parent, jane, bob},\n                      {parent, corrado, bob},\n                      {parent, jane, mark},\n                      {parent, corrado, mark},\n                      {parent, jane, alice},\n                      {parent, corrado, alice},\n                      {parent, bob, caesar},\n                      {parent, bob, anna},\n                      {parent, sara, casear},\n                      {parent, sara, anna}]),\n      ok.\n\nNow it's time to test our application:\n\n\n    Erlang (BEAM) emulator version 5.5 [source] [async-threads:0] [hipe]\n\n    Eshell V5.5  (abort with ^G)\n    1> c(relatives).\n    {ok,relatives}\n    2> relatives:start().\n    ok\n    3>\n\nFollowing the call to function *relatives:start/0*, the engine is\ncreated and populated; if no errors occurred, the rules should have\nbeen processed and the new facts derived. To check this, we can use\nthe function *seresye:get_kb/1*, which returns the list of facts\nasserted into the knowledge base of a given engine:\n\n\n    4> seresye:get_kb(relatives).\n    [{brother,bob,mark},\n     {sister,alice,bob},\n     {sister,alice,mark},\n     {brother,bob,alice},\n     {brother,mark,alice},\n     {grandmother,jane,caesar},\n     {grandfather,corrado,caesar},\n     {grandmother,jane,anna},\n     {grandfather,corrado,anna},\n     {sister,anna,caesar},\n     {brother,caesar,anna},\n     {sister,anna,casear},\n     {mother,sara,anna},\n     {mother,sara,casear},\n     {parent,sara,anna},\n     {father,bob,anna},\n     {parent,sara,casear},\n     {father,bob,caesar},\n     {parent,bob,anna},\n     {father,corrado,alice},\n     {parent,bob,caesar},\n     {mother,jane,alice},\n     {parent,corrado,alice},\n     {father,corrado,mark},\n     {parent,jane,alice},\n     {mother,jane,mark},\n     {parent,corrado|...},\n     {brother|...},\n     {...}|...]\n    5>\n\nThe presence of facts representing concepts like *father*, *sister*,\netc., proves that the rules seems to be working as expected.\n\nWe can however query the knowledge base using specific fact templates.\nFor example, if we want to know who are Alice's brothers, we can use\nthe function *seresye:query_kb/2* as follows:\n\n\n    6> seresye:query_kb(relatives, {brother, '_', alice}).\n    [{brother,bob,alice},{brother,mark,alice}]\n    7>\n\nThe facts returned conform to the relationships depicted in the figure\nabove, thus proving that the rules written are really working.\n\nAs the example shows, function *seresye:query_kb/2* takes the engine\nname as the first argument, while, for the second parameter, a tuple\nhas to be specified, representing the fact template to be matched; in\nsuch a tuple, the atom *'_'* plays the role of a wildcard. However, to\nspecify a more complex matching, a *fun* can be used as a tuple\nelement; this *fun* has to return a boolean value which indicates if\nthe element matches the template. For example, to select both Alice's\nand Anna's brothers, we can use the following function call:\n\n\n    7> seresye:query_kb(relatives, {brother, '_', fun (X) -> (X == alice) or (X == anna) end}).\n    [{brother,bob,alice},{brother,mark,alice},{brother,caesar,anna}]\n    8>\n\n\nConclusions\n-----------\n\nThis HowTo not only shows how to use the SERESYE engine to write an AI\napplication, but also highlights the versatility of the Erlang language:\nthe characteristics of functional and symbolic programming, together with\nthe possibility of performing *introspection* of function declaration,\ncan be successfully exploited for application domains which are completely\nnew for Erlang but can surely be very interesting.\n"
  },
  {
    "path": "examples/seresye_phil.erl",
    "content": "%%%  SERESYE, an ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php%\n-module(seresye_phil).\n\n-export([start/0, phil_spawn/1, philosopher/2, think/1, eat/1]).\n\n-define(N_PHIL, 5).\n\nstart() ->\n    application:start(seresye),\n    seresye:start(restaurant),\n    phil_spawn(0).\n\nphil_spawn(?N_PHIL) -> ok;\nphil_spawn(N) ->\n    seresye:assert(restaurant, {fork, N}),\n    spawn(phil, philosopher, [N, init]),\n    if N < (?N_PHIL) - 1 ->\n           seresye:assert(restaurant, {room_ticket, N});\n       true -> ok\n    end,\n    phil_spawn(N + 1).\n\nphilosopher(N, init) -> new_seed(), philosopher(N, ok);\nphilosopher(N, X) ->\n    think(N),\n    Ticket = seresye:wait_and_retract(restaurant,\n                                     {room_ticket, '_'}),\n    seresye:wait_and_retract(restaurant, {fork, N}),\n    seresye:wait_and_retract(restaurant,\n                            {fork, (N + 1) rem (?N_PHIL)}),\n    eat(N),\n    seresye:assert(restaurant, {fork, N}),\n    seresye:assert(restaurant,\n                  {fork, (N + 1) rem (?N_PHIL)}),\n    seresye:assert(restaurant, Ticket),\n    philosopher(N, X).\n\nthink(N) ->\n    io:format(\"~w: thinking ...~n\", [N]),\n    timer:sleep(random:uniform(10) * 1000).\n\neat(N) ->\n    io:format(\"~w: eating ...~n\", [N]),\n    timer:sleep(random:uniform(10) * 1000).\n\nnew_seed() ->\n    {_, _, X} = erlang:now(),\n    {H, M, S} = time(),\n    H1 = H * X rem 32767,\n    M1 = M * X rem 32767,\n    S1 = S * X rem 32767,\n    put(random_seed, {H1, M1, S1}).\n"
  },
  {
    "path": "examples/seresye_prodcons.erl",
    "content": "%%%  ERESYE, an ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_prodcons).\n\n-export([start/0, prod/1, cons/1, cons_1/1]).\n\nstart() ->\n    application:start(seresye),\n    eresye:start(pc),\n    spawn(prodcons, cons_1, [1]),\n    spawn(prodcons, cons_1, [2]),\n    spawn(prodcons, cons_1, [3]),\n    spawn(prodcons, prod, [0]),\n    ok.\n\nprod(20) -> ok;\nprod(Index) ->\n    eresye:assert(pc, {item, Index}), prod(Index + 1).\n\ncons(20) -> ok;\ncons(Index) ->\n    Fact = eresye:retract(pc,\n                          {item, fun (X) -> X == Index end}),\n    io:format(\"Consumer ~p~n\", [Fact]),\n    cons(Index + 1).\n\ncons_1(N) ->\n    Fact = eresye:wait_and_retract(pc, {item, '_'}),\n    io:format(\"~w: Consumer ~p~n\", [N, Fact]),\n    timer:sleep(random:uniform(500)),\n    cons_1(N).\n"
  },
  {
    "path": "examples/seresyee_auto.erl",
    "content": "%%%  SERESYE, an ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n%%% ======================================================\n%%%   Automotive Expert System\n%%%\n%%%     This expert system diagnoses some simple\n%%%     problems with a car.\n%%%\n%%%     It is a bare translation of the same example\n%%%     provided in CLIPS Version 6.0\n%%%\n%%%     To execute, type 'auto:start().'\n%%% ======================================================\n-module(seresyee_auto).\n\n-export([determine_battery_state/2,\n         determine_conductivity_test/4, determine_engine_state/2,\n         determine_gas_level/3, determine_knocking/2,\n         determine_low_output/2, determine_misfiring/2,\n         determine_point_surface_state_1/3,\n         determine_point_surface_state_2/2,\n         determine_rotation_state/2, determine_sluggishness/2,\n         no_repairs/2, normal_engine_state_conclusions/2,\n         print_repair/3, start/0,\n         unsatisfactory_engine_state_conclusions/2]).\n\n-neg_rule({determine_engine_state, [{'working-state', engine, '__IGNORE_UNDERSCORE__'},\n                                    {repair, '__IGNORE_UNDERSCORE__'}]}).\n\n-include_lib(\"seresye/include/seresye.hrl\").\n\n%% **********************\n%% * ENGINE STATE RULES *\n%% **********************\nnormal_engine_state_conclusions(Engine,\n                                {'working-state', engine, normal}) ->\n    seresye_engine:assert(Engine,\n                         [{repair, \"No repair needed.\"},\n                          {'spark-state', engine, normal},\n                          {'charge-state', battery, charged},\n                          {'rotation-state', engine, rotates}]).\n\nunsatisfactory_engine_state_conclusions(Engine,\n                                        {'working-state', engine,\n                                         unsatisfactory}) ->\n    seresye_engine:assert(Engine,\n                         [{'charge-state', battery, charged},\n                          {'rotation-state', engine, rotates}]).\n\n%% ***************\n%% * QUERY RULES *\n%% ***************\ndetermine_engine_state(Engine, {start, _})\n  when not {rule, [{'working-state', engine, _}, {repair, _}]} ->\n    case ask_yn('Does the engine start (yes/no)? ') of\n        true ->\n            case ask_yn('Does the engine run normally (yes/no)? ')\n            of\n                true ->\n                    seresye_engine:assert(Engine,\n                                         {'working-state', engine, normal});\n                _ ->\n                    seresye_engine:assert(Engine,\n                                         {'working-state', engine, unsatisfactory})\n            end;\n        _ ->\n            seresye_engine:assert(Engine,\n                                 {'working-state', engine, 'does-not-start'})\n    end.\n\ndetermine_rotation_state(Engine,\n                         {'working-state', engine, 'does-not-start'})\n  when not\n       {rule, [{'rotation-state', engine, _}, {repair, _}]} ->\n    case ask_yn('Does the engine rotate (yes/no)? ') of\n        true ->\n            seresye_engine:assert(Engine,\n                                 [{'rotation-state', engine, rotates},\n                                  {'spark-state', engine, 'irregular-spark'}]);\n        _ ->\n            seresye_engine:assert(Engine,\n                                 [{'rotation-state', engine, 'does-not-rotate'},\n                                  {'spark-state', engine, 'does-not-spark'}])\n    end.\n\ndetermine_sluggishness(Engine,\n                       {'working-state', engine, unsatisfactory})\n  when not {rule, [{repair, _}]} ->\n    case ask_yn('Is the engine sluggish (yes/no)? ') of\n        true ->\n            seresye_engine:assert(Engine, {repair, \"Clean the fuel line.\"});\n        _ -> Engine\n    end.\n\ndetermine_misfiring(Engine,\n                    {'working-state', engine, unsatisfactory})\n  when not {rule, [{repair, _}]} ->\n    case ask_yn('Does the engine misfire (yes/no)? ') of\n        true ->\n            seresye_engine:assert(Engine,\n                                 [{repair, \"Point gap adjustment.\"},\n                                  {'spark-state', engine, 'irregular-spark'}]);\n        _ -> Engine\n    end.\n\ndetermine_knocking(E,\n                   {'working-state', engine, unsatisfactory})\n  when not {rule, [{repair, _}]} ->\n    case ask_yn('Does the engine knock (yes/no)? ') of\n        true ->\n            seresye_engine:assert(E, {repair, \"Timing adjustment.\"});\n        _ -> E\n    end.\n\ndetermine_low_output(E,\n                     {'working-state', engine, unsatisfactory})\n  when not {rule, [{symptom, engine, _}, {repair, _}]} ->\n    case\n        ask_yn('Is the output of the engine low (yes/no)? ')\n    of\n        true ->\n            seresye_engine:assert(E, {symptom, engine, 'low-output'});\n        _ ->\n            seresye_engine:assert(E, {symptom, engine, 'not-low-output'})\n    end.\n\ndetermine_gas_level(E,\n                    {'working-state', engine, 'does-not-start'},\n                    {'rotation-state', engine, rotates})\n  when not {rule, [{repair, _}]} ->\n    case\n        ask_yn('Does the tank have any gas in it (yes/no)? ')\n    of\n        false -> seresye_engine:assert(E, {repair, \"Add gas.\"});\n        _ -> E\n    end.\n\ndetermine_battery_state(E,\n                        {'rotation-state', engine, 'does-not-rotate'})\n  when not\n       {rule, [{'charge-state', battery, _}, {repair, _}]} ->\n    case ask_yn('Is the battery charged (yes/no)? ') of\n        true ->\n            seresye_engine:assert(E, {'charge-state', battery, charged});\n        _ ->\n            seresye_engine:assert(E,\n                                 [{repair, \"Charge the battery.\"},\n                                  {'charge-state', battery, dead}])\n    end.\n\ndetermine_point_surface_state_1(E,\n                                {'working-state', engine, 'does-not-start'},\n                                {'spark-state', engine, 'irregular-spark'})\n  when not {rule, [{repair, _}]} ->\n    dpss(E).\n\ndetermine_point_surface_state_2(E,\n                                {symptom, engine, 'low-output'})\n  when not {rule, [{repair, _}]} ->\n    dpss(E).\n\ndpss(E) ->\n    case\n        ask_question('What is the surface state of the points (normal/burned/contaminated)? ')\n    of\n        [$b, $u, $r, $n, $e, $d | _] ->\n            seresye_engine:assert(E, {repair, \"Replace the points.\"});\n        [$c, $o, $n, $t, $a, $m, $i, $n, $a, $t, $e, $d | _] ->\n            seresye_engine:assert(E, {repair, \"Clean the points.\"});\n        _ -> E\n    end.\n\ndetermine_conductivity_test(E,\n                            {'working-state', engine, 'does-not-start'},\n                            {'spark-state', engine, 'does-not-spark'},\n                            {'charge-state', battery, charged})\n  when not {rule, [{repair, _}]}; true ->\n    case\n        ask_yn('Is the conductivity test for the ignition coil positive (yes/no)? ')\n    of\n        true ->\n            seresye_engine:assert(E,\n                                 {repair, \"Repair the distributor lead wire.\"});\n        _ ->\n            seresye_engine:assert(E, {repair, \"Replace the ignition coil.\"})\n    end.\n\nno_repairs(E, {start, _})\n  when not {rule, [{repair, _}]}, true ->\n    seresye_engine:assert(E,\n                         {repair, \"Take your car to a mechanic.\"}).\n\nprint_repair(E, {repair, X}, {start, _}) ->\n    io:format(\"Suggested Repair: ~p~n\", [X]), E.\n\nask_yn(Prompt) ->\n    [Response | _] = io:get_line(Prompt),\n    case Response of\n        $y -> true;\n        _ -> false\n    end.\n\nask_question(Prompt) -> io:get_line(Prompt).\n\nstart() ->\n    Engine0 = seresye_engine:new(),\n    %% Rules with high priority (10)\n    Engine2 = lists:foldl(fun (Rule, Engine1) ->\n                                  seresye_engine:add_rule(Engine1, {?MODULE, Rule}, 10)\n                          end,\n                          Engine0,\n                          [normal_engine_state_conclusions,\n                           unsatisfactory_engine_state_conclusions,\n                           print_repair]),\n    %% Rules with normal priority (0)\n    Engine3 = lists:foldl(fun (Rule, Engine1) ->\n                                  seresye_engine:add_rule(Engine1, {?MODULE, Rule})\n                          end,\n                          Engine2,\n                          [determine_engine_state, determine_rotation_state,\n                           determine_sluggishness, determine_misfiring,\n                           determine_knocking, determine_low_output,\n                           determine_gas_level, determine_battery_state,\n                           determine_point_surface_state_1,\n                           determine_point_surface_state_2,\n                           determine_conductivity_test]),\n    %% Rules with low priority (-10)\n    Engine4 = seresye_engine:add_rule(Engine3,\n                                     {?MODULE, no_repairs}, -10),\n    seresye_engine:assert(Engine4, {start, ok}).\n"
  },
  {
    "path": "features/seresyet_12.feature",
    "content": "Feature: Support explicit state passing in an seresye system\n  In order to make callbacks more easily accessible and less prone to requiring side effects\n  As an Erlang Developer\n  I want to be able to have my own per engine state\n  and have that state be passed to my rules when they execute\n\n  Scenario: Retrievable  state gets passed to rules\n    Given a seresye engine that is initialized with state\n    And initialized with data\n    When seresye propagation is complete\n    Then the per engine state is retrievable\n    And contains the data populated by the rules\n"
  },
  {
    "path": "features/seresyet_13.feature",
    "content": "Feature: Support defining rules via module attributes\n  In order to seresye more usable\n  As an Erlang Developer\n  I want to be able define my rules via rule attributes in the module file itself\n\n  Scenario: Rules are defined in the attribute itself\n    Given a seresye engine that is initialized with data\n    And rules from a module with rules defined via attributes\n    When when seresye propagation is complete\n    Then the engine runs normally\n    And contains the data populated by the rules\n"
  },
  {
    "path": "include/seresye.hrl",
    "content": "%% Parse transforms for automatic creating negative specs for rules in\n%% a rules file. though the user can write them in a spec it is much\n%% nicer to write them in a when clause and let the transform do its\n%% work.\n-compile({parse_transform, seresye_autoneg}).\n-compile({parse_transform, seresye_transform}).\n"
  },
  {
    "path": "rebar.config",
    "content": "{deps, \n  [\n   {edown, \".*\", {git, \"https://github.com/uwiger/edown.git\", {branch, \"master\"}}},\n   {erlware_commons, \".*\", {git, \"https://github.com/erlware/erlware_commons.git\", {branch, \"master\"}}},\n   {parse_trans, \".*\", {git, \"https://github.com/esl/parse_trans.git\", {branch, \"master\"}}}\n]}.\n"
  },
  {
    "path": "sinan.config",
    "content": "{project_name, seresye}.\n{project_vsn, \"0.0.4\"}.\n\n{compile_args, [debug_info, warnings_as_errors,\n               {warn_format, 2}, warn_export_all,\n               warn_export_vars, warn_shadow_vars, warn_obsolete_guard,\n               warn_unused_import]}.\n\n{ignore_dirs,  [\"_\",\n                \".\",\n                \"features\"]}.\n"
  },
  {
    "path": "src/internal.hrl",
    "content": "-record(seresye, {kb, alfa, join, agenda, pending_actions, client_state, fired_rule, hooks = []}).\n"
  },
  {
    "path": "src/seresye.app.src",
    "content": "%% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*-\n\n{application, seresye,\n [{description, \"SERESYE means Swarm oriented ERlang Expert SYstem Engine. It is a library \"\n   \"to write expert systems and rule processing engines using the Erlang \"\n   \"programming language\"},\n  {vsn, \"0.0.4\"},\n  {modules, []},\n  {registered, []},\n  {applications, [kernel, stdlib, erlware_commons]},\n  {mod, {seresye_app, []}}]}.\n"
  },
  {
    "path": "src/seresye.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye).\n\n%%====================================================================\n%% External exports\n%%====================================================================\n\n-export([start/0, start/1, start/2, stop/1, get_engine/1,\n         add_rules/2, add_rule/2, add_rule/3, assert/2, get_kb/1,\n         get_rules_fired/1, get_client_state/1,\n         set_hooks/2, get_fired_rule/1,\n         set_client_state/2, query_kb/2, serialize/1, \n         remove_rule/2, retract/2]).\n\n%% gen_server callbacks\n-export([start_link/0, start_link/1, start_link/2, init/1, handle_call/3,\n         handle_cast/2, handle_info/2, terminate/2, code_change/3]).\n\n%%====================================================================\n%% External functions\n%%====================================================================\nstart() ->\n    seresye_sup:start_engine().\n\nstart(Name) ->\n    seresye_sup:start_engine(Name).\n\nstart(Name, ClientState) ->\n    seresye_sup:start_engine(Name, ClientState).\n\nset_hooks(Name, Hooks) when is_list(Hooks) ->\n    gen_server:cast(Name, {set_hooks, Hooks}).\n\nset_client_state(Name, NewState) ->\n    gen_server:cast(Name, {set_client_state, NewState}).\n\nget_client_state(Name) ->\n    gen_server:call(Name, get_client_state).\n\nstop(EngineName) ->\n    (catch gen_server:call(EngineName, stop)),\n    ok.\n\nget_engine(EngineName) ->\n    gen_server:call(EngineName, get_engine).\n\n%% @doc Insert a fact in the KB.\n%% It also checks if the fact verifies any condition,\n%% if this is the case the fact is also inserted in the alpha-memory\nassert(Name, Facts) ->\n    gen_server:call(Name, {assert, Facts}, infinity).\n\n%% @doc removes a 'fact' in the Knowledge Base and if something occurs\n%% Condition is also deleted from the corresponding alpha-memory\nretract(Name, Facts) ->\n    gen_server:call(Name, {retract, Facts}, infinity).\n\nadd_rules(Name, RuleList)\n  when is_list(RuleList) orelse is_atom(RuleList) ->\n    gen_server:call(Name, {add_rules, RuleList}).\n\nadd_rule(Name, Fun) ->\n    gen_server:call(Name, {add_rule, Fun}).\n\nadd_rule(Name, Rule, Salience) ->\n    gen_server:call(Name, {add_rule, Rule, Salience}).\n\nremove_rule(Name, Rule) ->\n    gen_server:call(Name, {remove_rule, Rule}).\n\nget_rules_fired(Name) ->\n    gen_server:call(Name, get_rules_fired).\n\nget_fired_rule(Name) ->\n    gen_server:call(Name, get_fired_rule).    \n\nget_kb(Name) ->\n    gen_server:call(Name, get_kb).\n\nquery_kb(Name, Pattern) ->\n    gen_server:call(Name, {query_kb, Pattern}).\n\nserialize(Name) ->\n    gen_server:call(Name, serialize).\n\n%%%===================================================================\n%%% gen_server callbacks\n%%%===================================================================\nstart_link() ->\n    gen_server:start_link(?MODULE, [], []).\n\nstart_link(Name) when is_atom(Name) ->\n    gen_server:start_link({local, Name}, ?MODULE, [], []);\n\nstart_link(ClientState) when not is_atom(ClientState) ->\n    gen_server:start_link(?MODULE, [ClientState], []).\n\nstart_link(ClientState, Name) when is_atom(Name) ->\n    gen_server:start_link({local, Name}, ?MODULE, [ClientState], []).\n\n\ninit([]) ->\n    {ok, seresye_engine:new()};\ninit([Engine]) when element(1, Engine) == seresye ->\n    {ok, seresye_engine:restore(Engine)};\ninit([ClientState]) ->\n    {ok, seresye_engine:new(ClientState)}.\n\n\nhandle_call(get_client_state, _From, State) ->\n    Reply =\n        try\n            {ok, seresye_engine:get_client_state(State)}\n        catch\n            Type:Reason ->\n                {error, {Type, Reason}}\n        end,\n    {reply, Reply, State};\nhandle_call(stop, _From, State) ->\n    {stop, normal, State};\nhandle_call({assert, Facts}, _From, State0) ->\n    {Reply, State1} =\n        try\n            {ok, seresye_engine:assert(State0, Facts)}\n        catch\n            Type:Reason ->\n                {{error, {Type, Reason}}, State0}\n        end,\n    {reply, Reply, State1};\nhandle_call({retract, Facts}, _From, State0) ->\n    {Reply, State1} =\n        try\n            {ok, seresye_engine:retract(State0, Facts)}\n        catch\n            Type:Reason ->\n                {{error, {Type, Reason}}, State0}\n        end,\n    {reply, Reply, State1};\nhandle_call({add_rules, Rules}, _From, State0) ->\n    {Reply, State1} =\n        try\n            {ok, seresye_engine:add_rules(State0, Rules)}\n        catch\n            Type:Reason ->\n                {{error, {Type, Reason}}, State0}\n        end,\n    {reply, Reply, State1};\nhandle_call({add_rule, Rule}, _From, State0) ->\n    {Reply, State1} =\n        try\n            {ok, seresye_engine:add_rule(State0, Rule)}\n        catch\n            Type:Reason ->\n                {{error, {Type, Reason}}, State0}\n        end,\n    {reply, Reply, State1};\nhandle_call({add_rule, Rule, Salience}, _From, State0) ->\n    {Reply, State1} =\n        try\n            {ok, seresye_engine:add_rule(State0, Rule, Salience)}\n        catch\n            Type:Reason ->\n                {{error, {Type, Reason}}, State0}\n        end,\n    {reply, Reply, State1};\nhandle_call({remove_rule, Rule}, _From, State0) ->\n    {Reply, State1} =\n        try\n            {ok, seresye_engine:remove_rule(State0, Rule)}\n        catch\n            Type:Reason ->\n                {{error, {Type, Reason}}, State0}\n        end,\n    {reply, Reply, State1};\nhandle_call(get_rules_fired, _From, State0) ->\n    Reply =\n        try\n            seresye_engine:get_rules_fired(State0)\n        catch\n            Type:Reason ->\n                {error, {Type, Reason}}\n        end,\n    {reply, Reply, State0};\nhandle_call(get_fired_rule, _From, State0) ->\n    Reply =\n        try\n            seresye_engine:get_fired_rule(State0)\n        catch\n            Type:Reason ->\n                {error, {Type, Reason}}\n        end,\n    {reply, Reply, State0};\nhandle_call(get_engine, _From, State0) ->\n    {reply, State0, State0};\nhandle_call(get_kb, _From, State0) ->\n    Reply =\n        try\n            seresye_engine:get_kb(State0)\n        catch\n            Type:Reason ->\n                {error, {Type, Reason}}\n        end,\n    {reply, Reply, State0};\nhandle_call({query_kb, Pattern}, _From, State0) ->\n    Reply =\n        try\n            seresye_engine:query_kb(State0, Pattern)\n        catch\n            Type:Reason ->\n                {error, {Type, Reason}}\n        end,\n    {reply, Reply, State0};\n\nhandle_call(serialize, _From, State) ->\n    Reply = seresye_engine:serialize(State),\n    {reply, Reply, State}.\n\nhandle_cast({set_hooks, Hooks}, State) ->\n    {noreply, seresye_engine:set_hooks(State, Hooks)};\n\nhandle_cast({set_client_state, CS}, State) ->\n    {noreply, seresye_engine:set_client_state(State, CS)}.\n\nhandle_info(_Info, State) ->\n    {noreply, State}.\n\nterminate(_Reason, _State) ->\n    ok.\n\ncode_change(_OldVsn, State, _Extra) ->\n    {ok, State}.\n"
  },
  {
    "path": "src/seresye_agenda.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_agenda).\n\n-export([new/1, add_activation/3, add_activation/4,\n         breadth_order/2, clear_agenda/1, delete_activation/2,\n         delete_rule/2, depth_order/2, fifo_order/2,\n         get_activation/2, get_activation_from_name/2,\n         get_activation_salience/2, get_first_activation/1,\n         get_number_of_activations/1, get_rules_fired/1,\n         get_strategy/1, pop_rule/1,\n         set_activation_salience/3, set_rule_salience/3,\n         set_strategy/2]).\n\n-include(\"internal.hrl\").\n\n-record(agenda, {rules_fired, strategy, rule_list,\n                 exec_state, id, pending_actions}).\n\n%%====================================================================\n%% External functions\n%%====================================================================\nnew(Seresye) ->\n    Seresye#seresye{agenda=#agenda{rules_fired=0,\n                                 strategy=depth,\n                                 rule_list=[],\n                                 exec_state=nil,\n                                 pending_actions=[],\n                                 id=0}}.\n\nadd_activation(Agenda, Rule, Args) ->\n    add_activation(Agenda, Rule, Args, 0).\n\nadd_activation(EngineState0 = #seresye{agenda=\n                                          Agenda0 = #agenda{strategy=Strategy,\n                                                            rule_list=RuleList0,\n                                                            id=Id}},\n               Rule, Args, Salience) ->\n    RuleList1 = case Strategy of\n                    depth ->\n                        depth_add(RuleList0, Rule, Args, Salience, Id);\n                    breadth ->\n                        breadth_add(RuleList0, Rule, Args, Salience, Id);\n                    fifo ->\n                        fifo_add(RuleList0, Rule, Args, Salience, Id)\n                  end,\n    Agenda1 = Agenda0#agenda{rule_list=RuleList1, id=Id + 1},\n\n    execute_pending(after_activation_schedule(EngineState0#seresye{agenda=Agenda1})).\n\n\n%% @doc Remove all activation from Agenda,\n%% returns an empty agenda with same past strategy\nclear_agenda(EngineState = #seresye{agenda=Agenda0}) ->\n    EngineState#seresye{agenda=Agenda0#agenda{rule_list=[], id=0}}.\n\nget_strategy(#seresye{agenda=#agenda{strategy=Strategy}}) ->\n    Strategy.\n\nset_strategy(EngineState = #seresye{agenda=Agenda0 = #agenda{rule_list=RuleList0}}, NewStrategy) ->\n    RuleList1 = case NewStrategy of\n                    depth ->\n                        lists:sort(fun depth_order/2, RuleList0);\n                    breadth ->\n                        lists:sort(fun breadth_order/2,\n                                   RuleList0);\n                    fifo ->\n                        lists:sort(fun fifo_order/2, RuleList0);\n                    _ ->\n                        erlang:throw({seresye, {invalid_strategy, NewStrategy}})\n\n                end,\n    EngineState#seresye{agenda=Agenda0#agenda{strategy=NewStrategy, rule_list=RuleList1}}.\n\nget_rules_fired(#seresye{agenda=#agenda{rules_fired=Fired}}) ->\n    Fired.\n\n%% @doc Remove activation with id='Id' or\n%% all activation whose id is in the list passed as argument\ndelete_activation(EngineState, []) -> EngineState;\ndelete_activation(EngineState = #seresye{agenda=Agenda0 = #agenda{rule_list=RuleList0}},\n                 Id)\n  when not is_list(Id) ->\n    EngineState#seresye{agenda=Agenda0#agenda{rule_list=lists:keydelete(Id, 4, RuleList0)}};\ndelete_activation(EngineState, [Id | OtherId]) ->\n    EngineState1 = delete_activation(EngineState, Id),\n    delete_activation(EngineState1, OtherId).\n\n%% @doc Remove all activation associated with rule 'Rule' from the agenda,\n%% returns the modified agenda\ndelete_rule(EngineState = #seresye{agenda=Agenda0 = #agenda{rule_list=RuleList0}}, Rule) ->\n    ActList = proplists:lookup_all(Rule, RuleList0),\n    RuleList1 = lists:foldl(fun (X, R1) ->\n                                    lists:delete(X, R1)\n                            end,\n                            RuleList0, ActList),\n    EngineState#seresye{agenda=Agenda0#agenda{rule_list=RuleList1}}.\n\n%% @doc Returns the Id of activation associated to rule 'Rule' and\n%% arguments 'Args', false if it not present\nget_activation(#seresye{agenda=#agenda{rule_list=RuleList0}}, {Rule, Args}) ->\n    ActList = proplists:lookup_all(Rule, RuleList0),\n    case lists:keysearch(Args, 2, ActList) of\n        {value, {_, _, _, Id}} -> Id;\n        false -> false\n    end.\n\n%% @doc Returns the Id of first activation associated to rule 'Rule',\n%% false if 'Rule' is not present in the agenda\nget_activation_from_name(#seresye{agenda=#agenda{rule_list=RuleList0}}, Rule) ->\n    case lists:keysearch(Rule, 1, RuleList0) of\n        {value, {_, _, _, Id}} -> Id;\n        false -> false\n    end.\n\n%% @doc Return the Id associated to first activation in the agenda\n%% false if agenda is empty\nget_first_activation(#seresye{agenda=#agenda{rule_list=[First | _]}}) ->\n    element(4, First).\n\n%% @doc Return the salience value of activation with id='Id'\n%% false if Id is not present in the agenda\nget_activation_salience(#seresye{agenda=#agenda{rule_list=RuleList0, id=NextId}}, Id) ->\n    case NextId < Id of\n        true -> false;\n        false ->\n            case lists:keysearch(Id, 4, RuleList0) of\n                {value, {_, _, Salience, _}} -> Salience;\n                false -> false\n            end\n    end.\n\n%% @doc Sets the salience value of activation with id='Id',\n%% returns the modified agenda\nset_activation_salience(EngineState =\n                            #seresye{agenda=Agenda0 =\n                                        #agenda{rule_list=RuleList0, strategy=Strategy}}, Id, NewSalience)\n  when is_number(NewSalience) and not is_list(Id) ->\n    RuleList2 =\n        case lists:keysearch(Id, 4, RuleList0) of\n            {value, {Rule, Args, _Salience, Id}} ->\n                RuleList1 = lists:keyreplace(Id, 4, RuleList0,\n                                             {Rule, Args, NewSalience, Id}),\n                order(RuleList1, Strategy);\n            false ->\n                RuleList0\n        end,\n    EngineState#seresye{agenda=Agenda0#agenda{rule_list=RuleList2}};\nset_activation_salience(_EngineState, Id, NewSalience)\n  when not is_list(Id) ->\n    erlang:throw({seresye, {invalid_salience, NewSalience}});\nset_activation_salience(EngineState0, [Id | OtherId],\n                        NewSalience) ->\n    EngineState1 = set_activation_salience(EngineState0, Id, NewSalience),\n    set_activation_salience(EngineState1, OtherId, NewSalience).\n\n%% @doc Sets the salience value of all activations associated to rule 'Rule',\n%% returns the modified agenda\nset_rule_salience(EngineState0 =\n                    #seresye{agenda=#agenda{rule_list=RuleList0}}, Rule, NewSalience) ->\n    ActList = proplists:lookup_all(Rule, RuleList0),\n    IdList = [Id || {_, _, _, Id} <- ActList],\n    set_activation_salience(EngineState0, IdList,\n                            NewSalience).\n\n\n%%====================================================================\n%% Internal functions\n%%====================================================================\nexecute_pending(EngineState0 = #seresye{agenda = Agenda0 = #agenda{pending_actions=[PA | Rest]}}) ->\n    EngineState1 = PA(EngineState0#seresye{agenda=Agenda0#agenda{pending_actions=Rest}}),\n    execute_pending(EngineState1);\nexecute_pending(EngineState0 = #seresye{agenda = #agenda{pending_actions=[]}}) ->\n    EngineState0.\n\nafter_activation_schedule(EngineState0 =\n                              #seresye{agenda=Agenda0 =\n                                          #agenda{rule_list=RuleList0,\n                                                  exec_state=ExecState0,\n                                                  pending_actions=PA0,\n                                                  rules_fired=RF0}}) ->\n    {ExecState1, RuleList1, PA1, RF1} =\n        if\n            ExecState0 == active -> {ExecState0, RuleList0, PA0, RF0};\n            true ->\n                {RuleToExecute, RL} = pop_rule(RuleList0),\n                if\n                    RuleToExecute == false ->\n                        {nil, RL, PA0, RF0};\n                    true ->\n                        {active, RL, PA0 ++ [fun(EngineState) ->\n                                                     exec(EngineState, RuleToExecute)\n                                             end], RF0 + 1}\n                end\n        end,\n    EngineState0#seresye{agenda=Agenda0#agenda{exec_state=ExecState1,\n                                              rule_list=RuleList1,\n                                              pending_actions=PA1,\n                                              rules_fired=RF1}}.\n\nafter_execution_schedule(EngineState0 =\n                             #seresye{agenda=Agenda0 =\n                                         #agenda{rule_list=RuleList0,\n                                                 pending_actions=PA0,\n                                                 rules_fired=RF0}}) ->\n  {RuleToExecute, RL} = pop_rule(RuleList0),\n  {ExecState1, RuleList1, PA1, RF1} =\n    if\n      RuleToExecute == false -> {nil, RL, PA0, RF0};\n      true ->\n        {active, RL, PA0 ++ [fun(EngineState) ->\n                                     exec(EngineState, RuleToExecute)\n                             end], RF0 + 1}\n    end,\n    EngineState0#seresye{agenda=Agenda0#agenda{exec_state=ExecState1,\n                                              rule_list=RuleList1,\n                                              pending_actions=PA1,\n                                              rules_fired=RF1}}.\n\n%% @doc Remove the first activation, returns the rule,\n%% function arguments and the modified agenda\npop_rule([]) -> {false, []};\npop_rule([Activation | NewRuleList]) ->\n    {Activation, NewRuleList}.\n\ndepth_add(RuleList, Rule, Args, Salience, Id) ->\n    {L1, L2} = lists:splitwith(fun ({_, _, S, _}) ->\n                                       S > Salience\n                               end,\n                               RuleList),\n    L1 ++ [{Rule, Args, Salience, Id} | L2].\n\nbreadth_add(RuleList, Rule, Args, Salience, Id) ->\n    {L1, L2} = lists:splitwith(fun ({_, _, S, _}) ->\n                                       S >= Salience\n                               end,\n                               RuleList),\n    L1 ++ [{Rule, Args, Salience, Id} | L2].\n\nfifo_add(RuleList, Rule, Args, Salience, Id) ->\n    RuleList ++ [{Rule, Args, Salience, Id}].\n\nget_number_of_activations({_Strategy, RuleList, _NextId}) ->\n    length(RuleList).\n\norder(ActionList, Strategy) ->\n    case Strategy of\n        breadth ->\n            lists:sort(fun breadth_order/2, ActionList);\n        depth -> lists:sort(fun depth_order/2, ActionList);\n        fifo -> lists:sort(fun fifo_order/2, ActionList);\n        _Other -> ActionList\n    end.\n\n%% @doc define when an Act1 comes before Act2 in breadth strategy\nbreadth_order(Act1, Act2)\n  when element(3, Act1) > element(3, Act2) ->\n    true;\nbreadth_order(Act1, Act2)\n  when element(3, Act1) < element(3, Act2) ->\n    false;\nbreadth_order(Act1, Act2)\n  when element(4, Act1) > element(4, Act2) ->\n    false;\nbreadth_order(_Act1, _Act2) -> true.\n\n%% @doc define when an Act1 comes before Act2 in depth strategy\ndepth_order(Act1, Act2)\n  when element(3, Act1) > element(3, Act2) ->\n    true;\ndepth_order(Act1, Act2)\n  when element(3, Act1) < element(3, Act2) ->\n    false;\ndepth_order(Act1, Act2)\n  when element(4, Act1) < element(4, Act2) ->\n    false;\ndepth_order(_Act1, _Act2) -> true.\n\n%% @doc define when an Act1 comes before Act2 in fifo strategy\nfifo_order(Act1, Act2)\n  when element(4, Act1) > element(4, Act2) ->\n    false;\nfifo_order(_Act1, _Act2) -> true.\n\n%%====================================================================\n%% Executor functions\n%%====================================================================\nexec(EngineState0, R) ->\n    {Mod, Fun} = case R of\n                     {{M, F}, _, _, _} -> {M, F};\n                     _ -> {'_', '_'}\n                 end,\n    EngineState2 =\n        case catch execute_rule(EngineState0, R) of\n            {'EXIT', {function_clause, [{Mod, Fun, _} | _]}} -> EngineState0;\n            {'EXIT', {function_clause, [{Mod, Fun, _, _Location} | _]}} -> EngineState0;\n            {'EXIT', Reason} ->\n                erlang:throw({seresye, {rule_execution,\n                                       [R, Reason]}});\n            EngineState1 -> EngineState1\n        end,\n    after_execution_schedule(EngineState2).\n\n\n%% Fun = {Module, Function} or\n%% Fun = fun (...)\nexecute_rule(EngineState, {{M,F}, Args, X1, X2}) ->\n    L = length(Args) + 1,\n    execute_rule(EngineState, {fun M:F/L, Args, X1, X2});\nexecute_rule(EngineState, {Fun, Args, _, _}) when is_function(Fun) ->\n    case proplists:get_value(before_rule, EngineState#seresye.hooks) of\n        BF when is_function(BF) ->\n            BF(EngineState, Fun, Args);\n        _ ->\n            ignore\n    end,\n    Result = apply(Fun, [EngineState#seresye { fired_rule = {Fun, Args} } | Args]),\n    case proplists:get_value(after_rule, EngineState#seresye.hooks) of\n        AF when is_function(AF) ->\n            AF(Result, Fun, Args);\n        _ ->\n            ignore\n    end,\n    Result#seresye{ fired_rule = undefined }.\n\n"
  },
  {
    "path": "src/seresye_app.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_app).\n\n-behaviour(application).\n\n%% Application callbacks\n-export([start/2, stop/1]).\n\n%%%===================================================================\n%%% Application callbacks\n%%%===================================================================\n\nstart(_StartType, _StartArgs) ->\n    case seresye_sup:start_link() of\n        {ok, Pid} ->\n            {ok, Pid};\n        Error ->\n            Error\n                end.\n\nstop(_State) ->\n    ok.\n"
  },
  {
    "path": "src/seresye_autoneg.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2011, Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_autoneg).\n\n-export([parse_transform/2]).\n\nparse_transform(Forms, _Options) ->\n    {Head, NewAttributes, Body} =\n        lists:foldl(fun parse_forms/2, {[], [], []}, Forms),\n    lists:reverse(Head) ++ NewAttributes ++ lists:reverse(Body).\n\nparse_forms({function,Line,FunName, Arity, Clauses0}, {Head, Attrs0, Body}) ->\n    {_, Clauses2, Attrs2} =\n        lists:foldl(fun(Clause0, {ClauseCount, Clauses1, Attrs1}) ->\n                            case parse_clause(Clause0) of\n                                {false, Clause1} ->\n                                    {ClauseCount + 1,\n                                     [Clause1 | Clauses1],\n                                     Attrs1};\n                                {NewDetail, Clause1} ->\n                                    {ClauseCount + 1,\n                                     [Clause1 | Clauses1],\n                                     [{ClauseCount, NewDetail} | Attrs1]}\n                            end\n                end, {0, [], []}, Clauses0),\n\n    {Head, lists:map(fun({CC, Detail0}) ->\n                             {attribute, Line, rule_neg, {FunName, CC, Detail0}}\n                     end, Attrs2) ++ Attrs0,\n     [{function, Line, FunName, Arity, lists:reverse(Clauses2)} | Body]};\nparse_forms(F = {attribute,_,file,_}, {Head, Attrs0, Body}) ->\n    {[F | Head], Attrs0, Body};\nparse_forms(F = {attribute,_,module,_}, {Head, Attrs, Body}) ->\n    {[F | Head], Attrs, Body};\nparse_forms(El, {Head, Attrs, Body}) ->\n    {Head, Attrs, [El |Body]}.\n\nparse_clause({clause,Line, Args,\n              [[{op,_,'not',\n                 {tuple, _,\n                  [{atom,_,rule}, Neg]}} | AR] | OR],\n              Body}) ->\n    NewGuards = case AR of\n                    [] ->\n                        OR;\n                    _ ->\n                        [AR | OR]\n                end,\n    {rewrite_negs(Neg), {clause, Line, Args, NewGuards, Body}};\nparse_clause(Clause) ->\n    {false, Clause}.\n\nrewrite_negs({tuple, L, Elements}) ->\n    {tuple, L, lists:map(fun rewrite_negs/1, Elements)};\nrewrite_negs(C = {cons, _, _, _}) ->\n    rewrite_cons(C);\nrewrite_negs({var, Line, '_'}) ->\n    {atom, Line, '___IGNORE___'};\nrewrite_negs(Else) ->\n    Else.\n\nrewrite_cons({cons, Line, Element, nil}) ->\n    {cons, Line, rewrite_negs(Element), nil};\nrewrite_cons({cons, Line, E1, Rest}) ->\n    {cons, Line, rewrite_negs(E1), rewrite_negs(Rest)}.\n"
  },
  {
    "path": "src/seresye_engine.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_engine).\n\n-ifdef(debug).\n-define(LOG(F, X), io:format(F, X)).\n-else.\n-define(LOG(F, X), true).\n-endif.\n\n%%====================================================================\n%% Include files\n%%====================================================================\n-include(\"internal.hrl\").\n\n%%====================================================================\n%% External exports\n%%====================================================================\n\n-export([new/0, new/1, serialize/1, restore/1, cleanup/1,\n         set_hooks/2, get_fired_rule/1,\n         add_rules/2, add_rule/2, add_rule/3, assert/2, get_kb/1,\n         get_rules_fired/1, get_client_state/1, set_client_state/2,\n         query_kb/2, remove_rule/2, retract/2]).\n\n%%====================================================================\n%% External functions\n%%====================================================================\nnew() ->\n    new([]).\n\nnew(ClientState) ->\n    seresye_agenda:new(#seresye{kb=[], alfa=[],\n                              join=seresye_tree_list:new(),\n                              pending_actions=[],\n                              client_state=ClientState}).\n\nset_hooks(EngineState, Hooks) when is_list(Hooks) ->\n    EngineState#seresye{ hooks = Hooks }.\n\nset_client_state(EngineState, NewState) ->\n    EngineState#seresye{client_state=NewState}.\n\nget_client_state(#seresye{client_state=State}) ->\n    State.\n\ncleanup(#seresye{ alfa = Alfa0, join = Join0 }) ->\n    [ begin (catch ets:delete(Tab)), Tab end || {_, Tab, _} <- Alfa0 ] ++\n    [ begin (catch ets:delete(Tab)), Tab end || {{Tab, _}, _, _, _, _} <- Join0, is_integer(Tab) ].         \n\nrestore(#seresye{ alfa = Alfa0, join = Join0 } = Engine) ->\n    TabCache = ets:new(tab_cache, []),\n    Alfa = [ {Cond, restore_tab(TabCache, Tab), Alfa_fun}\n             || {Cond, Tab, Alfa_fun} <- Alfa0 ],\n    Join = [ {case Key of\n                  {Tab,V} when element(1,Tab) == ets_table ->\n                      {restore_tab(TabCache, Tab), V};\n                  _ ->\n                      Key\n              end, Beta, Children, Parent, Pos} ||\n               {Key, Beta, Children, Parent, Pos} <- Join0 ],\n    ets:delete(TabCache),\n    Engine#seresye{ alfa = Alfa, join = Join }.\n\nserialize(#seresye{ alfa = Alfa0, join = Join0 } = Engine) ->\n    Alfa = [ {Cond, serialize_tab(Tab), Alfa_fun} \n             || {Cond, Tab, Alfa_fun} <- Alfa0 ],\n    Join = [ {case Key of\n                  {Tab,V} when is_integer(Tab) ->\n                      {serialize_tab(Tab), V};\n                  _ ->\n                      Key\n              end, Beta, Children, Parent, Pos} ||\n               {Key, Beta, Children, Parent, Pos} <- Join0 ],\n    Engine#seresye{ alfa = Alfa, join = Join }.\n                 \n% where\nserialize_tab(Tab) ->\n    case ets:info(Tab) of\n        undefined ->\n            Tab;\n        Info ->\n            {ets_table, Tab, Info, ets:tab2list(Tab)}\n    end.\nrestore_tab(Cache, {ets_table, Tab, Info, Content}) ->\n    case ets:lookup(Cache, Tab) of\n        [{Tab, NewTab}] ->\n            NewTab;\n        [] ->\n            NewTab = ets:new(proplists:get_value(name, Info),\n                             [ proplists:get_value(Opt, Info) ||\n                                 Opt <- [type,protection] ] ++\n                             [ {Opt, proplists:get_value(Opt, Info)} || \n                                 Opt <- [keypos] ]),\n            ets:insert(NewTab, Content),\n            ets:insert(Cache, {Tab, NewTab}),\n            NewTab\n    end;\nrestore_tab(_Cache, Tab) ->\n    Tab.\n\n\n%% @doc Insert a fact in the KB.\n%% It also checks if the fact verifies any condition,\n%% if this is the case the fact is also inserted in the alpha-memory\nassert(EngineState0, Facts) when is_list(Facts) ->\n    lists:foldl(fun(Fact, EngineState1) ->\n                        assert(EngineState1, Fact)\n                end, EngineState0, Facts);\nassert(EngineState = #seresye{kb=Kb, alfa=Alfa}, Fact) when is_tuple(Fact) ->\n    execute_pending(case lists:member(Fact, Kb) of\n                        false ->\n                            Kb1 = [Fact | Kb],\n                            check_cond(EngineState#seresye{kb=Kb1}, Alfa,\n                                       {Fact, plus});\n                        true -> EngineState\n                    end).\n\n%% @doc removes a 'fact' in the Knowledge Base and if something occurs\n%% Condition is also deleted from the corresponding alpha-memory\nretract(EngineState0, Facts) when is_list(Facts) ->\n    lists:foldl(fun(Fact, EngineState1) ->\n                        retract(EngineState1, Fact)\n                end, EngineState0, Facts);\nretract(EngineState = #seresye{kb=Kb, alfa=Alfa}, Fact) when is_tuple(Fact) ->\n    execute_pending(case lists:member(Fact, Kb) of\n                        true ->\n                            Kb1 = Kb -- [Fact],\n                            check_cond(EngineState#seresye{kb=Kb1}, Alfa,\n                                       {Fact, minus});\n                        false -> EngineState\n                    end).\n\n\nadd_rules(EngineState0, RulesList) when is_list(RulesList) ->\n    lists:foldl(fun(Rule, EngineState1) ->\n                        add_rule(EngineState1, Rule)\n                end, EngineState0, RulesList);\nadd_rules(EngineState0, Module) when is_atom(Module) ->\n    AST = get_abstract_code(Module),\n    case get_rules(Module, AST) of\n        [] ->\n            erlang:throw({seresye, {no_rules_specified, Module}});\n        RulesList ->\n            lists:foldl(fun(Rule, EngineState1) ->\n                                add_rule(EngineState1, Rule)\n                        end, EngineState0, RulesList)\n    end.\n\nadd_rule(EngineState, {Module, Fun, ClauseID, Salience}) ->\n    add_rule(EngineState, {Module, Fun}, ClauseID, Salience);\nadd_rule(EngineState, Fun) ->\n    add_rule(EngineState, Fun, 0).\n\nadd_rule(EngineState, {Module, Fun, ClauseID}, Salience) ->\n    add_rule(EngineState, {Module, Fun}, ClauseID, Salience);\nadd_rule(EngineState, {Module, Fun}, Salience) ->\n    add_rule(EngineState, {Module, Fun}, 0, Salience).\n\nadd_rule(EngineState0, {Module, Fun}, ClauseID, Salience) ->\n    AST = get_abstract_code(Module),\n    case get_conds(Fun, ClauseID, AST) of\n        error -> erlang:throw({seresye, {error_extracting_conditions, Fun}});\n        CondsList ->\n            execute_pending(\n              lists:foldl(fun (X, EngineState1) ->\n                                  case X of\n                                      {error, Msg} ->\n                                          erlang:throw({seresye, {error_adding_rule,\n                                                         [Module, Fun, Msg]}});\n                                      {PConds, NConds} ->\n                                          ?LOG(\">> PConds=~p~n\", [PConds]),\n                                          ?LOG(\">> NConds=~p~n\", [NConds]),\n                                          add_rule__(EngineState1,\n                                                     {{Module, Fun}, Salience},\n                                                     {PConds, NConds})\n                                  end\n                          end,\n                          EngineState0,\n                          CondsList))\n    end.\n\nremove_rule(EngineState0, Rule) ->\n    execute_pending(remove_prod(seresye_agenda:delete_rule(EngineState0, Rule), Rule)).\n\nget_fired_rule(#seresye{ fired_rule = Rule }) ->\n    Rule.\n\nget_rules_fired(EngineState) ->\n    seresye_agenda:get_rules_fired(EngineState).\n\nget_kb(#seresye{kb=Kb}) ->\n    Kb.\n\nquery_kb(EngineState, Pattern) when is_tuple(Pattern) ->\n    PList = tuple_to_list(Pattern),\n    PatternSize = length(PList),\n    FunList = [if is_function(X) -> X;\n                  X == '_' -> fun (_) -> true end;\n                  true -> fun (Z) -> Z == X end\n               end\n               || X <- PList],\n    MatchFunction = fun (P) ->\n                            FunPatPairs = lists:zip(FunList, tuple_to_list(P)),\n                            FunEval = [F(X) || {F, X} <- FunPatPairs],\n                            MatchResult = lists:foldr(fun (X, Y) -> X and Y end,\n                                                      true, FunEval),\n                            MatchResult\n                    end,\n    KB = [X\n          || X <- get_kb(EngineState), size(X) == PatternSize],\n    lists:filter(MatchFunction, KB);\n\nquery_kb(Name, F) when is_function(F) ->\n    lists:filter(F, get_kb(Name)).\n\n%%====================================================================\n%% Internal functions\n%%====================================================================\nexecute_pending(EngineState0 = #seresye{pending_actions=[PA | Rest]}) ->\n    EngineState1 = PA(EngineState0#seresye{pending_actions=Rest}),\n    execute_pending(EngineState1);\nexecute_pending(EngineState0 = #seresye{pending_actions=[]}) ->\n    EngineState0.\n\nadd_rule__(EngineState0 = #seresye{join=Join},\n           Rule,\n           {PConds, NConds}) when is_tuple(Rule)->\n    Root = seresye_tree_list:get_root(Join),\n    case NConds of\n        [] ->\n            make_struct(EngineState0, Rule, PConds, [], Root,\n                        nil);\n        _ ->\n            {EngineState1, Np_node} = make_struct(EngineState0, Rule, NConds, [],\n                                                  Root, ng),\n            Root1 = seresye_tree_list:refresh(Root,\n                                             EngineState1#seresye.join),\n            make_struct(EngineState1, Rule, PConds, [], Root1,\n                        {Np_node, NConds})\n    end.\n\n%% @doc initializes the memory with a new alpha-present the facts\n%% In the Knowledge Base that satisfy the condition Cond\ninitialize_alfa(_, _, []) -> nil;\ninitialize_alfa(Cond, Tab, [Fact | Other_fact]) ->\n    Fun = prepare_match_alpha_fun(Cond),\n    case Fun(Fact) of\n        Fact ->\n            ets:insert(Tab, Fact),\n            initialize_alfa(Cond, Tab, Other_fact);\n        false -> initialize_alfa(Cond, Tab, Other_fact)\n    end.\n\nprepare_match_alpha_fun(Cond) ->\n    Expr =\n        [{'fun',1,\n          {clauses,[{clause,1,\n                     [{match,1,Cond,{var,1,'X__x__X'}}],\n                     [],\n                     [{var,1,'X__x__X'}]},\n                    {clause,1,[{var,1,'_'}],[],[{atom,1,false}]}]}}],\n    eval(Expr).\n\nget_abstract_code(Module) ->\n    case beam_lib:chunks(code:which(Module), [abstract_code]) of\n        {error, beam_lib, {file_error, File, enoent}} ->\n            erlang:throw({seresye,\n                          {unable_to_find_file, Module, File}});\n        {ok, {Module, [{abstract_code,no_abstract_code}]}} ->\n            erlang:throw({seresye,\n                          {no_abstract_code, Module,\n                           \"module must be compiled with +debug_info\"}});\n        {ok, {Module, [{abstract_code, {raw_abstract_v1, Forms}}]}} ->\n            Forms\n    end.\n\nget_conds(FunName, ClauseID, AST) ->\n    Records = get_records(AST, []),\n    case search_fun(FunName, AST) of\n        {error, Reason} ->\n            erlang:throw({seresye, {error_parsing_forms,\n                                   FunName, Reason}});\n        {ok, CL} ->\n            if ClauseID > 0 ->\n                    [read_clause(FunName, ClauseID,\n                                 lists:nth(ClauseID, CL), Records, AST)];\n               true ->\n                    [read_clause(FunName, ClauseID, Clause, Records, AST) ||\n                        Clause <- CL]\n            end\n    end.\n\nget_records([], Acc) ->\n    Acc;\nget_records([{attribute, _, record,\n              {RecordName, RecordFields}}\n             | Tail],\n            Acc) ->\n    NewAcc = [{RecordName,\n               get_record_fields(RecordFields, [])}\n              | Acc],\n    get_records(Tail, NewAcc);\nget_records([_ | Tail], Acc) ->\n    get_records(Tail, Acc).\n\nget_record_fields([], Acc) -> lists:reverse(Acc);\nget_record_fields([{typed_record_field, RecordField, _T} | Tail], Acc) ->\n    get_record_fields([RecordField | Tail], Acc);\nget_record_fields([{record_field, _,\n                    {atom, _, FieldName}, {nil, _}}\n                   | Tail],\n                  Acc) ->\n    NewAcc = [{FieldName, {nil, []}} | Acc],\n    get_record_fields(Tail, NewAcc);\nget_record_fields([{record_field, _,\n                    {atom, _, FieldName}, {Type, _, DefaultValue}}\n                   | Tail],\n                  Acc) ->\n    NewAcc = [{FieldName, {Type, DefaultValue}} | Acc],\n    get_record_fields(Tail, NewAcc);\nget_record_fields([{record_field, _,\n                    {atom, _, FieldName}}\n                   | Tail],\n                  Acc) ->\n    NewAcc = [{FieldName, {atom, undefined}} | Acc],\n    get_record_fields(Tail, NewAcc).\n\n\nget_rules(Module, AST) ->\n    get_rules(Module, AST, []).\n\nget_rules(_Module, [], Acc) ->\n    lists:reverse(Acc);\nget_rules(Module, [{attribute, _, rule, Rule} | Rest], Acc) ->\n    get_rules(Module, Rest, [resolve_rule(Module, Rule) | Acc]);\nget_rules(Module, [{attribute, _, rules, RuleList0} | Rest], Acc)\n  when is_list(RuleList0) ->\n    RuleList1 = [resolve_rule(Module, Rule) || Rule <- RuleList0],\n    get_rules(Module, Rest, RuleList1 ++ Acc);\nget_rules(Module, [_ | Rest], Acc) ->\n    get_rules(Module, Rest, Acc).\n\n\nresolve_rule(Module, Rule) when is_atom(Rule) ->\n    {Module, Rule, 0, 0};\nresolve_rule(Module, {Rule, Salience}) ->\n    {Module, Rule, 0, Salience};\nresolve_rule(Module, {Rule, Salience, ClauseID}) ->\n    {Module, Rule, ClauseID, Salience};\nresolve_rule(Module, Rule) ->\n    erlang:throw({seresye, {invalid_rule_definition, Module, Rule}}).\n\n\nsearch_fun([], _) ->\n    {error, \"function not found\"};\nsearch_fun(Func, [{function, _, Func, _, ClauseList} | _Rest]) ->\n    {ok, ClauseList};\nsearch_fun( Func, [_Tuple | Rest]) ->\n    search_fun(Func, Rest).\n\nread_clause(FunName, ClauseID, Clause, RecordList, AST) ->\n    {clause, _, ParamList, _, _} = Clause,\n    PosConds = read_parameters(ParamList, RecordList),\n    {PosConds, get_neg_conds(FunName, ClauseID, AST)}.\n\nget_neg_conds(FunName0, ClauseID0, AST) ->\n    lists:foldl(fun({attribute,_,rule_neg, {FunName1, ClauseID1, Detail}}, _)\n                   when ClauseID0 == ClauseID1, FunName0 == FunName1 ->\n                        neg_to_list(rewrite_negs(Detail), []);\n                   (_, Acc) ->\n                        Acc\n                end, [], AST).\n\nneg_to_list({cons, _, C1, Rest}, Acc) ->\n    neg_to_list(Rest, [C1 | Acc]);\nneg_to_list({nil, _}, Acc) ->\n    lists:reverse(Acc).\n\n\nrewrite_negs({tuple, _, Elements}) ->\n    {tuple, 0, lists:map(fun rewrite_negs/1, Elements)};\nrewrite_negs(C = {cons, _, _, _}) ->\n    rewrite_cons(C);\nrewrite_negs({atom, _, '___IGNORE___'}) ->\n    {var, 0, '_'};\nrewrite_negs(Else) ->\n    remove_line_numbers(Else).\n\nrewrite_cons({cons, _, Element, nil}) ->\n    {cons, 0, rewrite_negs(Element), nil};\nrewrite_cons({cons, _, E1, Rest}) ->\n    {cons, 0, rewrite_negs(E1), rewrite_negs(Rest)}.\n\nread_parameters([{var, _, _} | Tail], RecordList) ->\n    extract_parameters(Tail, RecordList, []).\n\nextract_parameters([], _, Acc) ->\n    lists:reverse(Acc);\nextract_parameters([{match, _, {record, _, _, _} = R,\n                     {var, _, _}}\n                    | Tail],\n                   RecordList,\n                   Acc) ->\n    extract_parameters([R | Tail], RecordList, Acc);\nextract_parameters([{match, _, Condition,\n                     {var, _, _}}\n                    | Tail],\n                   RecordList,\n                   Acc) ->\n    extract_parameters(Tail, RecordList, [remove_line_numbers(Condition) | Acc]);\nextract_parameters([{match, _, {var, _, _},\n                     {record, _, _, _} = R}\n                    | Tail],\n                   RecordList,\n                   Acc) ->\n    extract_parameters([R | Tail], RecordList, Acc);\nextract_parameters([{match, _, {var, _, _},\n                     Condition}\n                    | Tail],\n                   RecordList,\n                   Acc) ->\n    extract_parameters(Tail, RecordList, [remove_line_numbers(Condition) | Acc]);\nextract_parameters([{record, _, RecordName, Condition}\n                    | Tail],\n                   RecordList,\n                   Acc) ->\n    RecordDefinition = get_record_def(RecordName,\n                                      RecordList),\n    RecordDefaults = make_record_default(RecordDefinition,\n                                         []),\n    Pattern = {tuple, 0, [{atom, 0, RecordName}\n                          | make_record_pattern(Condition, RecordDefaults,\n                                                RecordDefinition)]},\n    extract_parameters(Tail, RecordList, [Pattern | Acc]);\nextract_parameters([{tuple, L, Elements}| Tail], RecordList, Acc) ->\n    Pattern = {tuple, L, \n               extract_parameters(Elements, RecordList, [])},\n    extract_parameters(Tail, RecordList, [Pattern | Acc]);\nextract_parameters([Condition | Tail], RecordList, Acc) ->\n    extract_parameters(Tail, RecordList, [remove_line_numbers(Condition) | Acc]).\n\n%% @doc removing the line numbers make it easier to compare conditions\n%% for equality\n%% Note since OTP 24 (https://github.com/erlang/otp/pull/3006)\n%% abstract code contains location conforming to\n%% {Line :: integer(), Column :: integer()} format,\n%% therefore additional clauses have been added\nremove_line_numbers(Values) when is_list(Values) ->\n    lists:map(fun remove_line_numbers/1, Values);\nremove_line_numbers({op, _, Op, T1, T2}) ->\n    {op, 0, Op, remove_line_numbers(T1), remove_line_numbers(T2)};\nremove_line_numbers({Type, {L,C}}) % >= OTP24\n  when is_integer(L), is_integer(C), is_atom(Type) ->\n    remove_line_numbers({Type, L});\nremove_line_numbers({Type, L})\n  when is_integer(L), is_atom(Type) ->\n    {Type, 0};\nremove_line_numbers({string, _, String}) ->\n    {string, 0, String};\nremove_line_numbers({Type, {L, C}, Values}) % >= OTP24\n  when is_integer(L), is_integer(C), is_atom(Type), is_list(Values) ->\n    remove_line_numbers({Type, L, Values});\nremove_line_numbers({Type, L, Values})\n  when is_integer(L), is_atom(Type), is_list(Values) ->\n    {Type, 0, lists:map(fun remove_line_numbers/1, Values)};\nremove_line_numbers({Type, {L, C}, Value}) % >= OTP24\n  when is_integer(L), is_integer(C), is_atom(Type) ->\n    remove_line_numbers({Type, L, Value});\nremove_line_numbers({Type, L, Value})\n  when is_integer(L), is_atom(Type) ->\n    {Type, 0, Value};\nremove_line_numbers({Type, {L, C}, C1, C2})\n  when is_integer(L), is_integer(C), is_atom(Type) ->\n    remove_line_numbers({Type, L, C1, C2});\nremove_line_numbers({Type, L, C1, C2}) % >= OTP24\n  when is_integer(L), is_atom(Type) ->\n    {Type, 0, remove_line_numbers(C1), remove_line_numbers(C2)}.\n\n\n\n\nget_record_def(_, []) -> nil;\nget_record_def(Name, [{Name, Definition} | _Rest]) ->\n    Definition;\nget_record_def(Name, [_ | Rest]) ->\n    get_record_def(Name, Rest).\n\nmake_record_default([], Acc) -> lists:reverse(Acc);\nmake_record_default([{_,_} | Tail], Acc) ->\n    make_record_default(Tail, [{var, 0, '_'} | Acc]).\n\nmake_record_pattern([], Pattern, _RecordDefinition) ->\n    Pattern;\nmake_record_pattern([{record_field, _,\n                      {atom, _, FieldName}, MatchValue}\n                     | Tail],\n                    Pattern, RecordDefinition) ->\n    FieldPosition = get_record_field_pos(FieldName,\n                                         RecordDefinition, 1),\n    NewPattern = lists:sublist(Pattern, FieldPosition - 1)\n        ++\n        [MatchValue] ++\n        lists:sublist(Pattern, FieldPosition + 1,\n                      length(Pattern) - FieldPosition),\n    make_record_pattern(Tail, NewPattern, RecordDefinition).\n\nget_record_field_pos(Name, [], _) ->\n    exit({bad_record_field, Name});\nget_record_field_pos(Name, [{Name, _} | _], Index) ->\n    Index;\nget_record_field_pos(Name, [{Name} | _], Index) ->\n    Index;\nget_record_field_pos(Name, [_ | Tail], Index) ->\n    get_record_field_pos(Name, Tail, Index + 1).\n\n\n%% @doc P and a list containing the conditions prior to Cond Of the\n%% same production\nmake_struct(EngineState0 = #seresye{join=Join}, _Rule, [], _P, Cur_node, ng) ->\n    %% create production node\n    Key = {np_node, nil},\n    {Node, {Join2, EngineState1}} =\n        case seresye_tree_list:child(Key, Cur_node, Join) of\n            false ->\n                Value = [],\n                {Node0, Join1} = seresye_tree_list:insert(Key, Value,\n                                                         Cur_node, Join),\n                {Node0, update_new_node(EngineState0, Node0, Cur_node,\n                                        Join1)};\n            Node0 -> {Node0, {Join, EngineState0}}\n        end,\n    {EngineState1#seresye{join=Join2}, Node};\nmake_struct(EngineState0 = #seresye{join=Join}, Rule, [], _P, Cur_node, nil) ->\n    %% create production node\n    Key = {p_node, Rule},\n    {Join2, EngineState1} = case seresye_tree_list:child(Key, Cur_node, Join) of\n                                false ->\n                                    Value = [],\n                                    {Node, Join1} = seresye_tree_list:insert(Key, Value,\n                                                                            Cur_node, Join),\n                                    update_new_node(EngineState0, Node, Cur_node,\n                                                    Join1);\n                                Node ->\n                                    {Fun, _Salience} = Rule,\n                                    Key1 = element(1, Node),\n                                    Sal = element(2, element(2, Key1)),\n                                    io:format(\">> Rule (~w) already present ~n\", [Fun]),\n                                    io:format(\">> with salience = ~w~n\", [Sal]),\n                                    io:format(\">> To change salience use 'set_salience()'.~n\"),\n                                    {Join, EngineState0}\n                            end,\n    EngineState1#seresye{join=Join2};\nmake_struct(EngineState0 = #seresye{join=Join}, Rule, [], P, Cur_node, {Nod, NConds}) ->\n    Id = seresye_tree_list:get_id(Nod),\n    {Cur_node1, Join1, EngineState1} = make_join_node(EngineState0, Join,\n                                                      {old, {n_node, Id}}, NConds, P,\n                                                      Cur_node),\n    Nod1 = seresye_tree_list:refresh(Nod, Join1),\n    Join2 = seresye_tree_list:set_child(Cur_node1, Nod1,\n                                       Join1),\n    Key = {p_node, Rule},\n    {Join4, EngineState2} =\n        case seresye_tree_list:child(Key, Cur_node1, Join2) of\n            false ->\n                Value = [],\n                {Node, Join3} = seresye_tree_list:insert(Key, Value,\n                                                        Cur_node1, Join2),\n                Cur_node2 = seresye_tree_list:refresh(Cur_node1, Join3),\n                update_new_node(EngineState1, Node, Cur_node2,\n                                Join3);\n            Node ->\n                {Fun, _Salience} = Rule,\n                Key1 = element(1, Node),\n                Sal = element(2, element(2, Key1)),\n                io:format(\">> Rule (~w) already present ~n\", [Fun]),\n                io:format(\">> with salience = ~w~n\", [Sal]),\n                io:format(\">> To change salience use 'set_salience()'.~n\"),\n                {Join2, EngineState1}\n        end,\n    EngineState2#seresye{join=Join4};\nmake_struct(EngineState0 = #seresye{join=Join}, Rule, [Cond | T], P, Cur_node, Nod) ->\n    {Alfa1, Tab} = add_alfa(EngineState0, Cond),\n    {Cur_node1, Join1, EngineState1} = make_join_node(EngineState0, Join, Tab,\n                                                      Cond, P, Cur_node),\n    P1 = P ++ [Cond],\n    make_struct(EngineState1#seresye{alfa=Alfa1, join=Join1}, Rule, T,\n                P1, Cur_node1, Nod).\n\nadd_alfa(#seresye{kb=Kb, alfa=Alfa}, Cond) ->\n    case is_present(Cond, Alfa) of\n        false ->\n            Tab = ets:new(alfa, [bag]),\n            Fun = [{'fun',1,\n                    {clauses,\n                     [{clause,1,\n                       [Cond],[],[{atom,1,true}]}]}}],\n            Alfa_fun = eval(Fun),\n            Alfa1 = [{Cond, Tab, Alfa_fun} | Alfa],\n            initialize_alfa(Cond, Tab, Kb),\n            {Alfa1, {new, Tab}};\n        {true, Tab} -> {Alfa, {old, Tab}}\n    end.\n\nremove_prod(EngineState0 = #seresye{join=Join}, Fun) ->\n    case seresye_tree_list:keysearch({p_node, Fun}, Join) of\n        false -> EngineState0;\n        Node ->\n            Parent_node = seresye_tree_list:get_parent(Node, Join),\n            Join1 = seresye_tree_list:remove_node(Node, Join),\n            Parent_node1 = seresye_tree_list:refresh(Parent_node,\n                                                    Join1),\n            EngineState1 = remove_nodes(Parent_node1,\n                                        EngineState0#seresye{join=Join1}),\n            remove_prod(EngineState1, Fun)\n    end.\n\nremove_nodes(Node, EngineState0 = #seresye{join=Join, alfa=Alfa}) ->\n    case seresye_tree_list:have_child(Node) of\n        false ->\n            case seresye_tree_list:is_root(Node) of\n                false ->\n                    Parent_node = seresye_tree_list:get_parent(Node, Join),\n                    Join1 = seresye_tree_list:remove_node(Node, Join),\n                    Parent_node1 = seresye_tree_list:refresh(Parent_node,\n                                                            Join1),\n                    {First, _} = seresye_tree_list:get_key(Node),\n                    case First of\n                        {n_node, IdNp_node} ->\n                            ParentKey = seresye_tree_list:get_key(Parent_node1),\n                            %% delete all nodes of the conditions negated\n                            Np_node = seresye_tree_list:get_node(IdNp_node, Join1),\n                            Join2 = seresye_tree_list:remove_child(Node, Np_node,\n                                                                  Join1),\n                            Np_node1 = seresye_tree_list:refresh(Np_node, Join2),\n                            EngineState1 = remove_nodes(Np_node1, EngineState0#seresye{join=Join2}),\n                            %% Recovery of the parent node of the node passed as an argument n_node\n                            %% The parent can now have a different id, but has the same key\n                            Join3 = EngineState1#seresye.join,\n                            Parent_node2 = seresye_tree_list:keysearch(ParentKey,\n                                                                      Join3),\n                            remove_nodes(Parent_node2, EngineState1);\n                        np_node ->\n                            remove_nodes(Parent_node1, EngineState0#seresye{join=Join1});\n                        Tab ->\n                            Alfa1 = case seresye_tree_list:is_present(Tab, Join1) of\n                                        false ->\n                                            ets:delete(Tab),\n                                            lists:keydelete(Tab, 2, Alfa);\n                                        true ->\n                                            Alfa\n                                    end,\n                            remove_nodes(Parent_node1,\n                                         EngineState0#seresye{alfa=Alfa1,\n                                                             join=Join1})\n                    end;\n                true -> EngineState0\n            end;\n        true -> EngineState0\n    end.\n\n%% @doc occurs and if the condition Cond is present\nis_present(_Cond, []) -> false;\nis_present(Cond, [{C1, Tab, _Alfa_fun} | Other_cond]) ->\n    case same_cond(Cond, C1) of\n        true -> {true, Tab};\n        false -> is_present(Cond, Other_cond)\n    end.\n\nsame_cond(Cond, Cond) -> true;\nsame_cond(_Cond1, _Cond2) -> false.\n\neval(Expr) ->\n    ?LOG(\"FUN = ~p~n\", [String]),\n    case catch erl_eval:exprs(Expr, erl_eval:new_bindings()) of\n        {'EXIT', _} -> false;\n        {value, Value, _Bindings} -> Value;\n        _ -> false\n    end.\n\nprepare_fun(_Cond, []) -> [{atom, 1, nil}];\nprepare_fun(Cond0, Cond1)\n  when not is_list(Cond0), is_list(Cond1) ->\n       [{'fun',1,\n         {clauses,\n          [{clause,1,\n            [Cond0,\n             prepare_rest(Cond1)],\n            [],\n            [{atom,1,true}]}]}}];\nprepare_fun(Cond0, Cond1)\n  when is_list(Cond0), is_list(Cond1) ->\n       [{'fun',1,\n         {clauses,\n          [{clause,1,\n            [prepare_rest(Cond0),\n             prepare_rest(Cond1)],\n            [],\n            [{atom,1,true}]}]}}].\n\nprepare_rest([Element | Rest]) ->\n    {cons, 1, Element, prepare_rest(Rest)};\nprepare_rest([]) ->\n    {nil, 1}.\n\n%% @doc join_node entering any new updates in the beta-token memory\nupdate_new_node(EngineState0, Node, Parent_node, Join) ->\n    case seresye_tree_list:is_root(Parent_node) of\n        false ->\n            Children = seresye_tree_list:children(Parent_node, Join),\n            case Children -- [Node] of\n                [] ->\n                    case seresye_tree_list:get_key(Parent_node) of\n                        {{n_node, _IdNp_node}, _Join_fun} ->\n                            Beta = seresye_tree_list:get_beta(Parent_node),\n                            update_from_n_node(EngineState0, Parent_node, Beta, Join);\n                        {Tab, _} ->\n                            Fact_list = ets:tab2list(Tab),\n                            update_new_node(EngineState0, Node, Parent_node, Join, Fact_list)\n                    end;\n                [Child | _Other_child] ->\n                    Beta = seresye_tree_list:get_beta(Child),\n                    Join1 = seresye_tree_list:update_beta(Beta, Node, Join),\n                    EngineState1 =\n                        case seresye_tree_list:get_key(Node) of\n                            {p_node, Rule} ->\n                                update_agenda(EngineState0, Beta, Rule);\n                            _Key ->\n                                EngineState0\n                        end,\n                    {Join1, EngineState1}\n            end;\n        true -> {Join, EngineState0}\n    end.\n\nupdate_agenda(EngineState, [], _Rule) -> EngineState;\nupdate_agenda(EngineState, [Tok | OtherTok], Rule) ->\n    EngineState1 = signal(EngineState, Tok, plus, Rule),\n    update_agenda(EngineState1, OtherTok, Rule).\n\nupdate_new_node(EngineState0, _Node, _Parent_node, Join, []) ->\n    {Join, EngineState0};\nupdate_new_node(EngineState0, Node, Parent_node, Join,\n                [Fact | Other_fact]) ->\n    Tok_list = right_act({Fact, plus}, Parent_node),\n    {Join1, EngineState1} = pass_tok(EngineState0, Tok_list, [Node], Join),\n    Node1 = seresye_tree_list:refresh(Node, Join1),\n    update_new_node(EngineState1, Node1, Parent_node, Join1, Other_fact).\n\nupdate_from_n_node(EngineState0, Parent_node, [], Join) ->\n    Join1 = seresye_tree_list:update_node(Parent_node, Join),\n    {Join1, EngineState0};\nupdate_from_n_node(EngineState0, Parent_node, [Tok | OtherTok], Join) ->\n    {Join1, EngineState1} = left_act(EngineState0, {Tok, plus}, [Parent_node],\n                                     Join),\n    update_from_n_node(Parent_node, OtherTok, Join1,\n                       EngineState1).\n\nsignal(EngineState0 = #seresye{pending_actions=PAList}, Token, Sign, {Fun, Salience}) ->\n    NewPA =\n        case Sign of\n            plus ->\n                fun(EngineState1) ->\n                        seresye_agenda:add_activation(EngineState1, Fun,\n                                                     Token, Salience)\n                end;\n            minus ->\n                ActivationId = seresye_agenda:get_activation(EngineState0,\n                                                            {Fun, Token}),\n                fun(EngineState1) ->\n                        seresye_agenda:delete_activation(EngineState1, ActivationId)\n                end\n        end,\n    EngineState0#seresye{pending_actions=PAList ++ [NewPA]}.\n\n%%====================================================================\n%% Fact Assertion/Retraction Functions\n%%====================================================================\ncheck_cond(EngineState, [], {_Fact, _Sign}) -> EngineState;\ncheck_cond(EngineState0, [{_C1, Tab, Alfa_fun} | T],\n           {Fact, Sign}) ->\n    case catch Alfa_fun(Fact) of\n        true ->\n            case Sign of\n                plus -> ets:insert(Tab, Fact);\n                minus -> ets:delete_object(Tab, Fact)\n            end,\n            EngineState1 = pass_fact(EngineState0, Tab, {Fact, Sign}),\n            check_cond(EngineState1, T, {Fact, Sign});\n        {'EXIT', {function_clause, _}} ->\n            check_cond(EngineState0, T, {Fact, Sign});\n        _Other -> check_cond(EngineState0, T, {Fact, Sign})\n    end.\n\n%% @doc propagates the 'done' to all the nodes that follow the alpha-memory\n%% With an index tab\npass_fact(EngineState0 = #seresye{join=Join}, Tab, {Fact, Sign}) ->\n    Succ_node_list = seresye_tree_list:lookup_all(Tab, Join),\n    {Join1, EngineState1} = propagate(EngineState0, Succ_node_list,\n                                      {Fact, Sign}, Join),\n    EngineState1#seresye{join=Join1}.\n\npropagate(EngineState0, [], {_Fact, _Sign}, Join) ->\n    {Join, EngineState0};\npropagate(EngineState0, [Join_node | T], {Fact, Sign}, Join) ->\n    Join_node1 = seresye_tree_list:refresh(Join_node, Join),\n    Tok_list = right_act({Fact, Sign}, Join_node1),\n    {Join1, EngineState1} =\n        case seresye_tree_list:get_key(Join_node1) of\n            {{n_node, _}, _} ->\n                propagate_nnode(EngineState0, Join_node1, Tok_list,\n                                Sign, Join);\n            {_Tab, _Fun} ->\n                Children_list = seresye_tree_list:children(Join_node1,\n                                                          Join),\n                pass_tok(EngineState0, Tok_list, Children_list,\n                         Join)\n        end,\n    propagate(EngineState1, T, {Fact, Sign}, Join1).\n\npropagate_nnode(EngineState0, _Join_node, [], _, Join) ->\n    {Join, EngineState0};\npropagate_nnode(EngineState0, Join_node, Tok_list, Sign, Join) ->\n    Children_list = seresye_tree_list:children(Join_node,\n                                              Join),\n    Toks = [make_toks(Tok, Sign) || Tok <- Tok_list],\n    case Sign of\n        plus -> pass_tok(EngineState0, Toks, Children_list, Join);\n        minus ->\n            {{n_node, IdNp_node}, Join_fun} =\n                seresye_tree_list:get_key(Join_node),\n            test_nnode(EngineState0, Toks, IdNp_node, Join_fun, Join_node, Join)\n    end.\n\nmake_toks(Tk, Sign) ->\n    L = element(1, Tk),\n    T1 = lists:sublist(L, length(L) - 1),\n    case Sign of\n        plus -> {T1, minus};\n        minus -> {T1, plus}\n    end.\n\n%% @doc Token propagates all the nodes in Children_list\npass_tok(EngineState0, [], _Children_list, Join) ->\n    {Join, EngineState0};\npass_tok(EngineState0, [Tok | T], Children_list, Join) ->\n    {Join1, EngineState1} = left_act(EngineState0, Tok, Children_list, Join),\n    Children_list1 = refresh(Children_list, Join1),\n    pass_tok(EngineState1, T, Children_list1, Join1).\n\n%% @doc Insert the token in Tok Beta_memory of Join_node, Token Tok\n%% compares the present with all the facts nell'alfa memory Associated\n%% with Join_node and if you have a successful propagates Token to the\n%% child nodes\nleft_act(EngineState0, {_Token, _Sign}, [], Join) ->\n    {Join, EngineState0};\nleft_act(EngineState0, {Token, Sign}, [Join_node | T], Join) ->\n    Beta = seresye_tree_list:get_beta(Join_node),\n    Beta1 =\n        case Sign of\n            plus -> Beta ++ [Token];\n            minus -> Beta -- [Token]\n        end,\n    Join1 = seresye_tree_list:update_beta(Beta1, Join_node,\n                                         Join),\n    case seresye_tree_list:get_key(Join_node) of\n        {p_node, Rule} ->\n            left_act(signal(EngineState0, Token, Sign, Rule),\n                     {Token, Sign}, T, Join1);\n        {{n_node, IdNp_node}, Join_fun} ->\n            left_act_nnode(EngineState0, {Token, Sign}, IdNp_node, Join_fun,\n                           [Join_node | T], Join1);\n        {np_node, nil} ->\n            Children_list = seresye_tree_list:children(Join_node,\n                                                      Join1),\n            {Join2, EngineState1} = propagate(EngineState0, Children_list,\n                                              {Token, Sign}, Join1),\n            left_act(EngineState1, {Token, Sign}, T, Join2);\n        {Tab, Join_fun} ->\n            Alfa_mem = ets:tab2list(Tab),\n            Tok_list = join_left({Token, Sign}, Alfa_mem, Join_fun),\n            Children_list = seresye_tree_list:children(Join_node,\n                                                      Join1),\n            {Join2, EngineState1} = pass_tok(EngineState0, Tok_list, Children_list,\n                                             Join1),\n            left_act(EngineState1, {Token, Sign}, T, Join2)\n    end.\n\njoin_left({Tok, Sign}, Mem, Join_fun) ->\n    lists:foldl(fun (WmeOrTok, Tok_list) ->\n                        Tok1 = match(WmeOrTok, Tok, Join_fun),\n                        case Tok1 of\n                            [] -> Tok_list;\n                            _Other -> Tok_list ++ [{Tok1, Sign}]\n                        end\n                end,\n                [], Mem).\n\nleft_act_nnode(EngineState0, {Token, Sign}, IdNp_node, Join_fun,\n               [Join_node | T], Join) ->\n    Np_node = seresye_tree_list:get_node(IdNp_node, Join),\n    BetaN = seresye_tree_list:get_beta(Np_node),\n    Tok_list = join_left({Token, Sign}, BetaN, Join_fun),\n    case Tok_list of\n        [] ->\n            Children_list = seresye_tree_list:children(Join_node,\n                                                      Join),\n            {Join1, EngineState1} = pass_tok(EngineState0, [{Token, Sign}],\n                                             Children_list, Join),\n            left_act(EngineState1, {Token, Sign}, T, Join1);\n        Tok_list -> left_act(EngineState0, {Token, Sign}, T, Join)\n    end.\n\ntest_nnode(EngineState0, [], _, _, _, Join) -> {Join, EngineState0};\ntest_nnode(EngineState0, [Tok | OtherTok], IdNpNode, Join_fun,\n           Join_node, Join) ->\n    {Join1, EngineState1} = left_act_nnode(EngineState0, Tok, IdNpNode,\n                                           Join_fun, [Join_node], Join),\n    test_nnode(EngineState1, OtherTok, IdNpNode, Join_fun, Join_node,\n               Join1).\n\n\n%% @doc WME compares with the new all tokens in the beta-memory Parent\n%% and returns a list of new tokens ([+ Tok1 WME, WME + Tok2,...])  Or\n%% an empty list if the WME not 'match' with tokens of Beta-memory\nright_act({Fact, Sign}, Join_node) ->\n    Beta = element(2, Join_node),\n    Join_fun = element(2, element(1, Join_node)),\n    join_right({Fact, Sign}, Beta, Join_fun).\n\njoin_right({Fact, Sign}, Beta, nil) ->\n    append(Beta, {Fact, Sign});\njoin_right({_Fact, _Sign}, [], _Join_fun) -> [];\njoin_right({Fact, Sign}, Beta, Join_fun) ->\n    join_right({Fact, Sign}, Beta, Join_fun, []).\n\njoin_right({_Fact, _Sign}, [], _Join_fun, PassedTok) ->\n    PassedTok;\njoin_right({Fact, Sign}, [Tok | T], Join_fun,\n           PassedTok) ->\n    Pass = match(Fact, Tok, Join_fun),\n    case Pass of\n        [] -> join_right({Fact, Sign}, T, Join_fun, PassedTok);\n        _New_tok ->\n            L = PassedTok ++ [{Pass, Sign}],\n            join_right({Fact, Sign}, T, Join_fun, L)\n    end.\n\nrefresh([], _Join, L) -> lists:reverse(L);\nrefresh([Node | OtherNode], Join, L) ->\n    Node1 = seresye_tree_list:refresh(Node, Join),\n    L1 = [Node1 | L],\n    refresh(OtherNode, Join, L1).\n\nrefresh(N, Join) -> refresh(N, Join, []).\n\n%% @doc WME is the match between the token and Tok and returns an\n%% empty list in case Negative or a new token (Tok + WME) if so\nmatch(Wme, Tok, Join_fun) ->\n    case catch Join_fun(Wme, Tok) of\n        true -> Tok ++ [Wme];\n        {'EXIT', {function_clause, _}} -> [];\n        _Other -> []\n    end.\n\nappend([], {Fact, Sign}) -> [{[Fact], Sign}];\nappend(Beta, {Fact, Sign}) ->\n    lists:foldl(fun (Tok, New_Beta) ->\n                        Tok1 = Tok ++ [Fact], New_Beta ++ {Tok1, Sign}\n                end,\n                [], Beta).\n\n%% @doc shares or create a join-node\nmake_join_node(EngineState0, J, {new, Tab}, Cond, P, Parent_node) ->\n    Join_fun = eval(prepare_fun(Cond, P)),\n    new_join(EngineState0, J, Tab, Join_fun, Parent_node);\nmake_join_node(EngineState0, J, {old, Tab}, Cond, P, Parent_node) ->\n    Result = seresye_tree_list:child(Tab, Parent_node, J),\n    case Result of\n        false ->\n            Join_fun = eval(prepare_fun(Cond, P)),\n            new_join(EngineState0, J, Tab, Join_fun, Parent_node);\n        Node -> {Node, J, EngineState0}\n    end.\n\nnew_join(EngineState0, J, Tab, Join_fun, Parent_node) ->\n    Key = {Tab, Join_fun},\n    Value = [],\n    {Node, J1} = seresye_tree_list:insert(Key, Value,\n                                         Parent_node, J),\n    {J2, EngineState1} = update_new_node(EngineState0, Node, Parent_node, J1),\n    Node1 = seresye_tree_list:refresh(Node, J2),\n    {Node1, J2, EngineState1}.\n"
  },
  {
    "path": "src/seresye_speedtest.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module (seresye_speedtest).\n-export([remove_multiple/3, final_rule/2, run_sieve/0]).\n\n\nremove_multiple(Engine, {X}, {Y}) when ((X rem Y) == 0) and (X =/= Y)->\n    seresye_engine:retract (Engine, {X}).\n\nfinal_rule(Engine0, {is, started} = X)\n  when not [\"{is, finished}\"];true ->\n    Engine1 = seresye_engine:retract (Engine0, X),\n    seresye_engine:assert (Engine1, {is, finished}).\n\nrun_sieve() ->\n    Start = now(),\n    Engine1 = seresye_engine:assert (seresye_engine:new(),\n                             [{X} || X <- lists:seq (2, 200)]),\n    Engine2 = seresye_engine:add_rule (Engine1, {?MODULE, remove_multiple}, 2),\n    Engine3 = seresye_engine:add_rule (Engine2, {?MODULE, final_rule}, 1),\n    Engine4 = seresye_engine:assert (Engine3, {is, started}),\n    End = now(),\n    io:format(\"Kb ~p~n\", [seresye_engine:get_kb (Engine4)]),\n    R = seresye_engine:get_rules_fired (Engine4),\n    io:format (\"Rules fired: ~p~n\", [R]),\n    D = timer:now_diff(End, Start),\n    io:format (\"Time = ~p sec, ~p rules/sec, rule execution time ~p msec~n\",\n               [D / 1000000.0,\n                R / (D / 1000000.0),\n                (D / 1000.0) / R]).\n"
  },
  {
    "path": "src/seresye_sup.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% All rights reserved.\n%%% Copyright (c) 2011, Afiniate, Inc.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_sup).\n\n-behaviour(supervisor).\n\n%% API\n-export([start_link/0, start_engine/0, start_engine/1, start_engine/2]).\n\n%% Supervisor callbacks\n-export([init/1]).\n\n-define(SERVER, ?MODULE).\n\n%%%===================================================================\n%%% API functions\n%%%===================================================================\n\nstart_link() ->\n    supervisor:start_link({local, ?SERVER}, ?MODULE, []).\n\nstart_engine() ->\n    supervisor:start_child(?SERVER, []).\n\nstart_engine(Name) ->\n    supervisor:start_child(?SERVER, [Name]).\n\nstart_engine(Name, ClientState) ->\n    supervisor:start_child(?SERVER, [Name, ClientState]).\n\n%%%===================================================================\n%%% Supervisor callbacks\n%%%===================================================================\ninit([]) ->\n    RestartStrategy = simple_one_for_one,\n    MaxRestarts = 1000,\n    MaxSecondsBetweenRestarts = 3600,\n\n    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},\n\n    Restart = transient,\n    Shutdown = 2000,\n    Type = worker,\n\n    AChild = {seresye, {seresye, start_link, []},\n              Restart, Shutdown, Type, [seresye]},\n\n    {ok, {SupFlags, [AChild]}}.\n"
  },
  {
    "path": "src/seresye_transform.erl",
    "content": "-module(seresye_transform).\n-export([parse_transform/2]).\n\n-record(state,{ \n          rules = [],\n          rule_functions = [],\n          exports = [],\n          options\n         }).\n\n-record(context, {module,\n                  function,\n                  arity,\n                  file,\n                  options}).\n\n\nparse_transform(Forms, Options) ->\n    #context{ file = File } = parse_trans:initial_context(Forms, Options),\n    case erl_lint:module(Forms, File, [nowarn_unused_function,nowarn_unused_vars,nowarn_unused_record]) of\n        {error, _Errors, _Warnings} ->\n            Forms;\n        _ ->\n            {Forms1, State} = parse_trans:transform(fun do_transform/4, \n                                             #state{ options = Options },\n                                                    Forms, Options),\n            Result0 = parse_trans:revert(Forms1),\n            lists:foldl(fun ({Fun, Arity}, Acc) ->\n                                parse_trans:export_function(Fun, Arity, Acc)\n                        end, Result0, State#state.rule_functions)\n    end.\n\ndo_transform(attribute,{attribute, _, export, Exports} = Attr, _Context, #state{} = State) ->\n    {Attr, true, State#state{ exports = State#state.exports ++ Exports }};\n\ndo_transform(attribute,{attribute, _, rule, Rule} = Attr, _Context, #state{ rules = Rs } = State) ->\n    {Attr, false, State#state{ rules = [rule_name(Rule)|Rs] }};\n\ndo_transform(attribute,{attribute, _, rules, Rules0} = Attr, _Context, #state{ rules = Rs } = State) ->\n    Rules = [ rule_name(R) || R <- Rules0 ],\n    {Attr, false, State#state{ rules = Rules ++ Rs }};\n\ndo_transform(function, {function, _, Fun, Arity, _Cs} = Form, _Context, #state{ rules = Rules, rule_functions = RFuns } = State) ->\n    case lists:member(Fun, Rules) of\n        false ->\n            {Form, true, State};\n        true ->\n            {Form, true, State#state{ rule_functions = [{Fun, Arity}|RFuns] -- State#state.exports }}\n    end;\n\n\ndo_transform(_Type, Form, _Context, State) ->\n    {Form, true, State}.\n\nrule_name(A) when is_atom(A) ->\n    A;\nrule_name({A, _}) ->\n    A.\n"
  },
  {
    "path": "src/seresye_tree_list.erl",
    "content": "%%%  SERESYE, an Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresye_tree_list).\n\n-export([child/3, children/2, get_beta/1, get_id/1,\n         get_key/1, get_last_insert/1, get_node/2, get_parent/2,\n         get_root/1, have_child/1, insert/4, is_present/2,\n         is_root/1, keysearch/2, lookup_all/2, new/0, refresh/2,\n         remove_child/3, remove_node/2, set_child/3,\n         update_beta/3, update_key/3, update_node/2]).\n\nnew() -> [{root, nil, [], 0, 1}].\n\ninsert(Key, Value, ParentNode, List) ->\n    {ParentKey, ParentValue, Children, Parent, Pos} =\n        ParentNode,\n    Next = length(List) + 1,\n    Node = {Key, Value, [], Pos, Next},\n    List1 = List ++ [Node],\n    Children1 = Children ++ [Next],\n    ParentNode1 = {ParentKey, ParentValue, Children1,\n                    Parent, Pos},\n    L1 = lists:keyreplace(Pos, 5, List1, ParentNode1),\n    {Node, L1}.\n\n%% @doc Parent_node search for children of a node whose key (tuple) is equal to Key\n%% if Key is not 'look for the node a tuple whose first element' {Key, _}\n%% Returns the node itself or false if there is no tuple\nchild(Key, ParentNode, List) ->\n    Children = element(3, ParentNode),\n    search(Key, List, Children).\n\nsearch(_Key, _List, []) -> false;\nsearch(Key, List, [NthElement | T]) ->\n    Elem = lists:nth(NthElement, List),\n    Res = search(Key, Elem),\n    case Res of\n        true -> Elem;\n        false -> search(Key, List, T)\n    end.\n\nsearch({p_node, Fun},\n       {{p_node, {Fun, _}}, _, _, _, _}) ->\n    true;\nsearch({p_node, Fun, _},\n       {{p_node, {Fun, _}}, _, _, _, _}) ->\n    true;\nsearch({Tab, Fun}, {{Tab, Fun}, _, _, _, _}) -> true;\nsearch(Tab, {{Tab, _}, _, _, _, _}) -> true;\nsearch(_K, _E) -> false.\n\ntest(X, X) -> true;\ntest(_X, _Y) -> false.\n\nget_root([]) -> nil;\nget_root([Root | _T]) ->\n    case is_root(Root) of\n        true -> Root;\n        false -> nil\n    end.\n\nis_root({root, _, _, _, _}) -> true;\nis_root(_Node) -> false.\n\n%% @doc Check if there is an alpha-memory join_node\n%% true if there is at least one, otherwise false\nis_present(_Tab, []) -> false;\nis_present(Tab, [Node | T]) ->\n    case catch element(1,\n                       element(1, Node)) % The first element of the list\n    of\n        {'EXIT',\n         {badarg, _}} ->                 % throws an exception\n            is_present(Tab, T);\n        TabElem ->\n            case test(TabElem, Tab) of\n                true -> true;\n                false -> is_present(Tab, T)\n            end\n    end.\n\n%% @doc returns a list of all the elements associated with the List\n%% Key Key. If there is no element with the requested key\n%% The result is' an empty list  = Tab Key\n%% Key =% {Tab} Join_fun\n%% Key =% {p_node, Fun}\n%% Key =% {p_node, Fun {, _}}\nlookup_all(Key, [_Root | L]) ->\n    lists:foldl(fun (Elem, ResultList) ->\n                        case search(Key, Elem) of\n                            true ->\n                                [Elem | ResultList];\n                            false -> ResultList\n                        end\n                end,\n                [], L).\n\n%% @doc Search for an item with key Key and returns the first found or false\nkeysearch(_Key, []) -> false;\nkeysearch(Key, [Node | OtherNode]) ->\n    case search(Key, Node) of\n        false -> keysearch(Key, OtherNode);\n        true -> Node\n    end.\n\n%% @doc returns all child nodes of Join_node\n%% Or an empty list if no successors Join_node\nchildren(Join_node, List) ->\n    Pos_list = element(3, Join_node),\n    lists:foldl(fun (Pos, Children) ->\n                        Elem = lists:nth(Pos, List), Children ++ [Elem]\n                end,\n                [], Pos_list).\n\nupdate_node(JoinNode, List) ->\n    Pos = element(5, JoinNode),\n    lists:keyreplace(Pos, 5, List, JoinNode).\n\nget_node(Id, List) -> lists:nth(Id, List).\n\nget_last_insert(List) ->\n    N = length(List), lists:nth(N, List).\n\nget_id(Node) -> element(5, Node).\n\nrefresh(Node, List) ->\n    Pos = element(5, Node), lists:nth(Pos, List).\n\nget_beta(Node) -> element(2, Node).\n\nupdate_beta(BetaNew, {Key, _BetaOld, Children, Parent, Pos}, List) ->\n    NewNode = {Key, BetaNew, Children, Parent, Pos},\n    lists:keyreplace(Pos, 5, List, NewNode).\n\nget_key(Node) -> element(1, Node).\n\nupdate_key(NewKey, {_Key, Beta, Children, Parent, Pos}, List) ->\n    NewNode = {NewKey, Beta, Children, Parent, Pos},\n    lists:keyreplace(Pos, 5, List, NewNode).\n\nget_parent(Node, List) ->\n    Parent = element(4, Node), lists:nth(Parent, List).\n\nhave_child(Node) ->\n    Children = element(3, Node),\n    case Children of\n        [] -> false;\n        _Other -> true\n    end.\n\nremove_child(Child, ParentNode, List) ->\n    ChildId = element(5, Child),\n    {Key, Value, Children, Parent, Pos} = ParentNode,\n    NewNode = {Key, Value, Children -- [ChildId], Parent,\n                Pos},\n    lists:keyreplace(Pos, 5, List, NewNode).\n\nset_child(Child, ParentNode, List) ->\n    {Key, Value, Children, Parent, Pos} = ParentNode,\n    ChildId = element(5, Child),\n    NewNode = {Key, Value, Children ++ [ChildId], Parent,\n                Pos},\n    lists:keyreplace(Pos, 5, List, NewNode).\n\nremove_node(Node, List) ->\n    Pos = element(5, Node),\n    ParentNode = get_parent(Node, List),\n    List1 = remove_child(Node, ParentNode, List),\n    Head = lists:sublist(List1, Pos - 1),\n    Tail = lists:nthtail(Pos, List1),\n    update_list(Head, Tail, Pos).\n\nupdate_list(List, [], _N) -> List;\nupdate_list(List, [Node | T], N) ->\n    NewPos = length(List) + 1,\n    {Key, Value, Children, Parent, Pos} = Node,\n    {NewParent, List1} =\n        case Parent > N of\n            true ->\n                {Parent - 1, List};\n            false ->\n                NewParent0 = Parent,\n                {Key1, Value1, Children1, Parent1, Pos1} =\n                    lists:nth(NewParent0, List),\n                ParentNode = {Key1, Value1,\n                              (Children1 -- [Pos]) ++ [NewPos], Parent1, Pos1},\n                {NewParent0, lists:keyreplace(Parent, 5, List, ParentNode)}\n        end,\n    NewChildren = [update_list_1(V1, N) || V1 <- Children],\n    NewNode = {Key, Value, NewChildren, NewParent,\n               NewPos},\n    List2 = List1 ++ [NewNode],\n    update_list(List2, T, N).\n\nupdate_list_1(X, N) ->\n    case X > N of\n        true -> X - 1;\n        false -> X\n    end.\n"
  },
  {
    "path": "test/seresyet_12.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2011, Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresyet_12).\n\n-export([given/3, then/3, 'when'/3]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\ngiven([initialized, with, data], Engine, _) ->\n    {ok,\n     seresye_engine:assert(Engine,\n                           [{male, bob}, {mail, joe}, {male, corrado},\n                            {female, sara}, {parent, bob, joe}, {parent, sara, bob},\n                            {parent, corrado, bob}])};\ngiven([a, seresye, engine, that, is, initialized, with,\n       state],\n      _, _) ->\n    Engine0 = seresye_engine:new([]),\n    Engine1 = lists:foldl(fun (X, Engine1) ->\n                                  seresye_engine:add_rule(Engine1,\n                                                          {seresyet_simple_relatives, X})\n                          end,\n                          Engine0, [mother, father, grandfather, grandmother]),\n    {ok, Engine1}.\n\n'when'([seresye, propagation, is, complete],\n       Engine, _) ->\n    %% Propagation happens immediately, so nothing to do here. Its\n    %% just a placeholder\n    {ok, Engine}.\n\nthen([the, per, engine, state, is, retrievable],\n     Engine, _) ->\n    {ok, {Engine, seresye_engine:get_client_state(Engine)}};\nthen([contains, the, data, populated, by, the, rules],\n     State = {_, InternalState}, _) ->\n    ?assertMatch(true,\n                 (lists:member({grandmother, sara, joe},\n                               InternalState))),\n    ?assertMatch(true,\n                 (lists:member({grandfather, corrado, joe},\n                               InternalState))),\n    ?assertMatch(true,\n                 (lists:member({mother, sara, bob}, InternalState))),\n    ?assertMatch(true,\n                 (lists:member({mother, sara, bob}, InternalState))),\n    ?assertMatch(true,\n                 (lists:member({father, corrado, bob}, InternalState))),\n    ?assertMatch(true,\n                 (lists:member({father, bob, joe}, InternalState))),\n    {ok, State}.\n"
  },
  {
    "path": "test/seresyet_13.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php-module(eresyet_13).\n-module(seresyet_13).\n\n-export([given/3, 'when'/3, then/3]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\ngiven([a, seresye, engine, that, is, initialized, with, data], _State, _) ->\n    Engine0 = seresye_engine:new([]),\n    {ok,\n     seresye_engine:assert(Engine0,\n                          [{male, bob}, {mail, joe}, {male, corrado},\n                           {female, sara}, {parent, bob, joe}, {parent, sara, bob},\n                           {parent, corrado, bob}])};\ngiven([rules,from,a,module,with,rules,defined,via,attributes], Engine, _) ->\n  {ok, seresye_engine:add_rules(Engine, seresyet_simple_relatives)}.\n\n'when'(['when',seresye,propagation,is,complete], Engine, _) ->\n    %% Propagation happens immediately, so nothing to do here. Its\n    %% just a placeholder\n    {ok, Engine}.\n\nthen([contains,the,data,populated,by,the,rules],\n     State = {_, InternalState}, _) ->\n    ?assertMatch(true,\n                 (lists:member({grandmother, sara, joe},\n                               InternalState))),\n    ?assertMatch(true,\n                 (lists:member({grandfather, corrado, joe},\n                               InternalState))),\n    ?assertMatch(true,\n                 (lists:member({mother, sara, bob}, InternalState))),\n    ?assertMatch(true,\n                 (lists:member({mother, sara, bob}, InternalState))),\n    ?assertMatch(true,\n                 (lists:member({father, corrado, bob}, InternalState))),\n    ?assertMatch(true,\n                 (lists:member({father, bob, joe}, InternalState))),\n    {ok, State};\nthen([the, engine, runs, normally], Engine, _) ->\n     {ok, {Engine, seresye_engine:get_client_state(Engine)}}.\n\n"
  },
  {
    "path": "test/seresyet_cannibals.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n%%% ======================================================\n%%%    Cannibals and Missionaries Problem\n%%%\n%%%     Another classic AI problem. The point is\n%%%     to get three cannibals and three missionaries\n%%%     across a stream with a boat that can only\n%%%     hold two people. If the cannibals outnumber\n%%%     the missionaries on either side of the stream,\n%%%     then the cannibals will eat the missionaries.\n%%%\n%%%     It is a bare translation of the same example\n%%%     provided in CLIPS Version 6.0\n%%%\n%%% ======================================================\n-module (seresyet_cannibals).\n\n-export([shore_1_move/3,\n         shore_2_move/3,\n         cannibals_eat_missionaries/2,\n         circular_path/3,\n         recognize_solution/2]).\n\n-record (status, {'search-depth',\n                  'parent',\n                  'shore-1-missionaries',\n                  'shore-1-cannibals',\n                  'shore-2-missionaries',\n                  'shore-2-cannibals',\n                  'boat-location'}).\n\n\n-define (INITIAL_MISSIONARIES, 3).\n-define (INITIAL_CANNIBALS, 3).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\n-rules([shore_1_move,\n        shore_2_move,\n        {cannibals_eat_missionaries, 10},\n        {circular_path, 10},\n        {recognize_solution, 10}]).\n\nfor (Min, Max) when Min > Max -> [];\nfor (Min, Max) -> lists:seq (Min, Max).\n\nshore_1_move (Engine0,\n              #status {'boat-location' = 'shore-1'} = Node,\n              {'boat-can-host', Limit}) ->\n    Num = Node#status.'search-depth',\n    S1M = Node#status.'shore-1-missionaries',\n    S1C = Node#status.'shore-1-cannibals',\n    S2M = Node#status.'shore-2-missionaries',\n    S2C = Node#status.'shore-2-cannibals',\n\n    MaxMissionaries = lists:min ([S1M, Limit]),\n\n    lists:foldl (\n      fun (Missionaries, Engine1) ->\n              MinCannibals = lists:max ([0, 1 - Missionaries]),\n              MaxCannibals = lists:min ([S1C, Limit - Missionaries]),\n\n              %%io:format (\"Shore 1 ~p,~p~n\", [MinCannibals, MaxCannibals]),\n\n              lists:foldl (\n                fun (Cannibals, Engine2) ->\n                        NewNode =\n                            #status { 'search-depth' = Num + 1,\n                                      'parent' = Node,\n                                      'shore-1-missionaries' = S1M - Missionaries,\n                                      'shore-1-cannibals' =  S1C - Cannibals,\n                                      'shore-2-missionaries' =  Missionaries + S2M,\n                                      'shore-2-cannibals' = Cannibals + S2C,\n                                      'boat-location' = 'shore-2'},\n\n                        seresye_engine:assert(Engine2, NewNode)\n                end,\n                Engine1,\n                for (MinCannibals, MaxCannibals))\n      end,\n      Engine0,\n      for (0, MaxMissionaries)).\n\n\nshore_2_move (Engine0,\n              #status {'boat-location' = 'shore-2'} = Node,\n              {'boat-can-host', Limit}) ->\n    Num = Node#status.'search-depth',\n    S1M = Node#status.'shore-1-missionaries',\n    S1C = Node#status.'shore-1-cannibals',\n    S2M = Node#status.'shore-2-missionaries',\n    S2C = Node#status.'shore-2-cannibals',\n\n    MaxMissionaries = lists:min ([S2M, Limit]),\n\n    lists:foldl(\n      fun (Missionaries, Engine1) ->\n              MinCannibals = lists:max ([0, 1 - Missionaries]),\n              MaxCannibals = lists:min ([S2C, Limit - Missionaries]),\n\n              lists:foldl (\n                fun (Cannibals, Engine2) ->\n                        NewNode =\n                            #status { 'search-depth' = Num + 1,\n                                      'parent' = Node,\n                                      'shore-1-missionaries' = S1M + Missionaries,\n                                      'shore-1-cannibals' = S1C + Cannibals,\n                                      'shore-2-missionaries' =  S2M - Missionaries,\n                                      'shore-2-cannibals' = S2C - Cannibals,\n                                      'boat-location' = 'shore-1'},\n                        seresye_engine:assert (Engine2, NewNode)\n                end,\n                Engine1,\n                for (MinCannibals, MaxCannibals))\n      end,\n      Engine0,\n      for (0, MaxMissionaries)).\n\n\n\ncannibals_eat_missionaries (Engine0,\n                            #status {'shore-1-missionaries' = S1M,\n                                     'shore-1-cannibals' = S1C,\n                                     'shore-2-missionaries' = S2M,\n                                     'shore-2-cannibals' =  S2C} = Node) ->\n    if\n        ((S2C > S2M) and (S2M =/= 0)) or ((S1C > S1M) and (S1M =/= 0)) ->\n            %%io:format (\"Invalid ~p~n\", [Node]),\n            seresye_engine:retract (Engine0, Node);\n        true -> Engine0\n    end.\n\n\ncircular_path  (Engine0,\n                #status {'search-depth' = SD1,\n                         'boat-location' = BL,\n                         'shore-1-missionaries' = S1M,\n                         'shore-1-cannibals' = S1C,\n                         'shore-2-missionaries' = S2M,\n                         'shore-2-cannibals' = S2C},\n                #status {'search-depth' = SD2,\n                         'boat-location' = BL,\n                         'shore-1-missionaries' = S1M,\n                         'shore-1-cannibals' = S1C,\n                         'shore-2-missionaries' = S2M,\n                         'shore-2-cannibals' = S2C} = Node) ->\n    if\n        SD1 < SD2 -> seresye_engine:retract (Engine0, Node);\n        true -> Engine0\n    end.\n\n\nrecognize_solution (Engine0,\n                    #status {'shore-2-missionaries' = M,\n                             'shore-2-cannibals' = C} = Node) ->\n    if\n        (M == ?INITIAL_MISSIONARIES) and (C == ?INITIAL_CANNIBALS) ->\n            Engine1 = seresye_engine:retract (Engine0, Node),\n            seresye_engine:set_client_state(Engine1, Node);\n        true -> Engine0\n    end.\n\nrules_test() ->\n    Engine0 = seresye_engine:new(),\n    Engine2 = seresye_engine:add_rules(Engine0, ?MODULE),\n\n    Engine3 =\n        seresye_engine:assert (Engine2,\n                               #status {'search-depth' =  1,\n                                        'parent' =  'no-parent',\n                                        'shore-1-missionaries' = ?INITIAL_MISSIONARIES,\n                                        'shore-2-missionaries' = 0,\n                                        'shore-1-cannibals' = ?INITIAL_CANNIBALS,\n                                        'shore-2-cannibals' = 0,\n                                        'boat-location' = 'shore-1'}),\n    Engine4 = seresye_engine:assert (Engine3, {'boat-can-host', 2}),\n    P = seresye_engine:get_client_state(Engine4),\n    verify_result(P).\n\nverify_result(Node = #status{'shore-2-missionaries'=S2M,\n                             'shore-2-cannibals'=S2C}) ->\n    ?assertMatch(?INITIAL_MISSIONARIES, S2M),\n    ?assertMatch(?INITIAL_CANNIBALS, S2C),\n    verify_result_(Node).\n\nverify_result_(#status{'parent' =  'no-parent'}) ->\n    ok;\nverify_result_(#status{'parent' =  Parent,\n                       'shore-1-missionaries'=S1M,\n                       'shore-1-cannibals'=S1C,\n                       'shore-2-missionaries'=S2M,\n                       'shore-2-cannibals'=S2C}) ->\n    ?assertMatch(true, (S1M >= S1C orelse S1M == 0)),\n    ?assertMatch(true, (S2M >= S2C orelse S2M == 0)),\n    verify_result_(Parent).\n"
  },
  {
    "path": "test/seresyet_relatives.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011, Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module (seresyet_relatives).\n\n-export([father/3, grandfather/3, grandmother/3,\n         mother/3, brother/4, sister/4]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\n-rules([mother, father, brother, sister, grandfather,\n        grandmother]).\n\n%%\n%% if (X is female) and (X is Y's parent) then (X is Y's mother)\n%%\nmother (Engine, {female, X}, {parent, X, Y}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {mother, X, Y}),\n                                    [{mother, X, Y} | seresye_engine:get_client_state(Engine)]).\n\n\n%%\n%% if (X is male) and (X is Y's parent) then (X is Y's father)\n%%\nfather (Engine, {male, X}, {parent, X, Y}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {father, X, Y}),\n                                    [{father, X, Y} | seresye_engine:get_client_state(Engine)]).\n\n\n%%\n%% if (Y and Z have the same parent X) and (Z is female)\n%%    then (Z is Y's sister)\n%%\nsister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {sister, Z, Y}),\n                                    [{sister, Z, Y} | seresye_engine:get_client_state(Engine)]).\n\n\n%%\n%% if (Y and Z have the same parent X) and (Z is male)\n%%    then (Z is Y's brother)\n%%\nbrother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {brother, Z, Y}),\n                                    [{brother, Z, Y} | seresye_engine:get_client_state(Engine)]).\n\n\n%%\n%% if (X is Y's father) and (Y is Z's parent)\n%%    then (X is Z's grandfather)\n%%\ngrandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {grandfather, X, Z}),\n                                    [{grandfather, X, Z}\n                                     | seresye_engine:get_client_state(Engine)]).\n\n%%\n%% if (X is Y's mother) and (Y is Z's parent)\n%%    then (X is Z's grandmother)\n%%\ngrandmother (Engine, {mother, X, Y}, {parent, Y, Z}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {grandmother, X, Z}),\n                                    [{grandmother, X, Z}\n                                     | seresye_engine:get_client_state(Engine)]).\n\n\nrules_test() ->\n    Engine0 = seresye_engine:new([]),\n    Engine2 =  seresye_engine:add_rules(Engine0, ?MODULE),\n\n    Engine3 = seresye_engine:assert (Engine2,\n                                     [{male, bob},\n                                      {male, corrado},\n                                      {male, mark},\n                                      {male, caesar},\n                                      {female, alice},\n                                      {female, sara},\n                                      {female, jane},\n                                      {female, anna},\n                                      {parent, jane, bob},\n                                      {parent, corrado, bob},\n                                      {parent, jane, mark},\n                                      {parent, corrado, mark},\n                                      {parent, jane, alice},\n                                      {parent, corrado, alice},\n                                      {parent, bob, caesar},\n                                      {parent, bob, anna},\n                                      {parent, sara, casear},\n                                      {parent, sara, anna}]),\n\n    InternalState = seresye_engine:get_client_state(Engine3),\n\n    ?assertMatch(true,\n                 lists:member({mother,sara,anna}, InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({sister,anna,casear},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({mother,sara,casear},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({grandfather,corrado,anna},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({sister,anna,caesar},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,caesar,anna},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({father,bob,anna},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({grandmother,jane,anna},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({grandfather,corrado,caesar},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({father,bob,caesar},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({grandmother,jane,caesar},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({sister,alice,mark},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,bob,alice},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,mark,alice},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({father,corrado,alice},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({sister,alice,bob},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({sister,alice,mark},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,bob,alice},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,mark,alice},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({mother,jane,alice},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({sister,alice,bob},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,bob,mark},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({father,corrado,mark},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,mark,bob},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,bob,mark},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({mother,jane,mark},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({brother,mark,bob},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({father,corrado,bob},\n                              InternalState)),\n\n    ?assertMatch(true,\n                 lists:member({mother,jane,bob},\n                              InternalState)),\n\n    ?assertMatch(29, erlang:length(InternalState)).\n\n\n\n"
  },
  {
    "path": "test/seresyet_sample.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module (seresyet_sample).\n-export ([rule/4, rule1/3, rule2/4, rule3/3, start/0]).\n\n-record (sample_record, { a = nil, b}).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\n\nrule (Engine, {hello, world}, {ciao, X}, {X, 10}) ->\n    seresye_engine:set_client_state(Engine,\n                                    [rule | seresye_engine:get_client_state(Engine)]).\n\nrule1 (Engine0, {hello, world}, {ciao, _X} = F) ->\n    Engine1 = seresye_engine:assert (Engine0, {test}),\n    Engine2 = seresye_engine:retract (Engine1, F),\n    seresye_engine:set_client_state(Engine2,\n                                    [rule1a | seresye_engine:get_client_state(Engine2)]);\nrule1 (Engine, {hello, world}, {test}) ->\n    seresye_engine:set_client_state(Engine,\n                                    [rule1b | seresye_engine:get_client_state(Engine)]).\n\n\nrule2 (Engine, {hello, world}, #sample_record { a = Z }, {mondo, Z}) ->\n    seresye_engine:set_client_state(Engine,\n                                    [rule2 | seresye_engine:get_client_state(Engine)]).\n\nrule3 (Engine, {hello, [_H|T]}, {test, T}) ->\n    seresye_engine:set_client_state(Engine,\n                                    [rule3 | seresye_engine:get_client_state(Engine)]).\n\nstart () ->\n\n    Engine0 = seresye_engine:add_rule (seresye_engine:new([]), {?MODULE, rule2}),\n    Engine1 = seresye_engine:assert (Engine0, [[{ciao, mondo}, {mondo, 20}],\n                                               {hello, world},\n                                               {ok, world},\n                                               #sample_record { a = 10, b = 50}]),\n    Engine2 = seresye_engine:add_rule (Engine1, {?MODULE, rule3}),\n    Engine3 = seresye_engine:assert (Engine2, [{hello, [ciao, mondo]},\n                                               {test, ciao},\n                                               {test, [ciao]},\n                                               {test, [mondo]},\n                                               {hello, [ciao, mondo, world]},\n                                               {test, [mondo, world]}]),\n\n    Engine4 = seresye_engine:add_rules (Engine3, [{?MODULE, rule},\n                                                  {?MODULE, rule1}]),\n\n    Engine5 = seresye_engine:retract (Engine4, {test}),\n    State = seresye_engine:get_client_state(seresye_engine:assert (Engine5, {test})),\n    ?assertMatch([rule1b,rule1b,rule1a,rule3,rule3],\n                 State).\n"
  },
  {
    "path": "test/seresyet_sieve.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module (seresyet_sieve).\n-export([remove_multiple/3, final_rule/2, run_sieve/0]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n-include_lib(\"seresye/include/seresye.hrl\").\n\n-rules([{remove_multiple, 2},\n        {final_rule, 1}]).\n\nremove_multiple (Engine, {X}, {Y}) when ((X rem Y) == 0) and (X =/= Y)->\n    seresye_engine:retract (Engine, {X}).\n\nfinal_rule (Engine0, {is, started} = X)\n  when not {rule, [{is, finished}]} ->\n    Engine1 = seresye_engine:retract (Engine0, X),\n    seresye_engine:assert (Engine1, {is, finished}).\n\nrun_sieve() ->\n    Start = now(),\n    Engine1 = seresye_engine:assert (seresye_engine:new(),\n                             [{X} || X <- lists:seq (2, 100)]),\n    Engine2 = seresye_engine:add_rules(Engine1, ?MODULE),\n    Engine3 = seresye_engine:assert (Engine2, {is, started}),\n    End = now(),\n    ?assertMatch([{is,finished},\n                  {97},\n                  {89},\n                  {83},\n                  {79},\n                  {73},\n                  {71},\n                  {67},\n                  {61},\n                  {59},\n                  {53},\n                  {47},\n                  {43},\n                  {41},\n                  {37},\n                  {31},\n                  {29},\n                  {23},\n                  {19},\n                  {17},\n                  {13},\n                  {11},\n                  {7},\n                  {5},\n                  {3},\n                  {2}], seresye_engine:get_kb (Engine3)),\n    R = seresye_engine:get_rules_fired (Engine3),\n    io:format (\"Rules fired: ~p~n\", [R]),\n    D = timer:now_diff(End, Start),\n    io:format (\"Time = ~p sec, ~p rules/sec, rule execution time ~p msec~n\",\n               [D / 1000000.0,\n                R / (D / 1000000.0),\n                (D / 1000.0) / R]).\n\nrules_test_() ->\n         {timeout, 160,\n          fun() ->\n                  run_sieve()\n          end}.\n"
  },
  {
    "path": "test/seresyet_simple_relatives.erl",
    "content": "%%%  SERESYE, a Swarm oriented ERlang Expert SYstem Engine\n%%%\n%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro\n%%% Copyright (c) 2011 Afiniate, Inc.\n%%% All rights reserved.\n%%%\n%%% You may use this file under the terms of the BSD License. See the\n%%% license distributed with this project or\n%%% http://www.opensource.org/licenses/bsd-license.php\n-module(seresyet_simple_relatives).\n\n-export([father/3, grandfather/3, grandmother/3,\n         mother/3]).\n\n-include_lib(\"eunit/include/eunit.hrl\").\n\n-rule(mother).\n-rule(father).\n-rules([{grandfather, 10},\n        grandmother]).\n%%\n%% if (X is female) and (X is Y's parent) then (X is Y's mother)\n%%\nmother(Engine, {female, X}, {parent, X, Y}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {mother, X, Y}),\n                                    [{mother, X, Y} | seresye_engine:get_client_state(Engine)]).\n\n%%\n%% if (X is male) and (X is Y's parent) then (X is Y's father)\n%%\nfather(Engine, {male, X}, {parent, X, Y}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {father, X, Y}),\n                                    [{father, X, Y} | seresye_engine:get_client_state(Engine)]).\n\n%%\n%% if (X is Y's father) and (Y is Z's parent)\n%%    then (X is Z's grandfather)\n%%\ngrandfather(Engine, {father, X, Y}, {parent, Y, Z}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {grandfather, X, Z}),\n                                    [{grandfather, X, Z}\n                                     | seresye_engine:get_client_state(Engine)]).\n\n%%\n%% if (X is Y's mother) and (Y is Z's parent)\n%%    then (X is Z's grandmother)\n%%\ngrandmother(Engine, {mother, X, Y}, {parent, Y, Z}) ->\n    seresye_engine:set_client_state(seresye_engine:assert(Engine,\n                                                          {grandmother, X, Z}),\n                                    [{grandmother, X, Z}\n                                     | seresye_engine:get_client_state(Engine)]).\n\nrules_test() ->\n    Engine0 = seresye_engine:new([]),\n    Engine2 =\n        lists:foldl(fun (X, Engine1) ->\n                            seresye_engine:add_rule (Engine1, {?MODULE, X})\n                    end,\n                    Engine0,\n                    [mother, father, grandfather, grandmother]),\n\n    Engine3 = seresye_engine:assert(Engine2, [{male, bob},\n                                              {mail, joe},\n                                              {male, corrado},\n                                              {female, sara},\n                                              {parent, bob, joe},\n                                              {parent, sara, bob},\n                                              {parent, corrado, bob}]),\n    InternalState = seresye_engine:get_client_state(Engine3),\n\n\n    ?assertMatch(true,\n                 lists:member({grandmother, sara, joe}, InternalState)),\n    ?assertMatch(true,\n                 lists:member({grandfather, corrado, joe}, InternalState)),\n    ?assertMatch(true,\n                 lists:member({mother, sara, bob}, InternalState)),\n    ?assertMatch(true,\n                 lists:member({father, corrado, bob}, InternalState)),\n    ?assertMatch(true,\n                 lists:member({father, bob, joe}, InternalState)),\n    ?assertMatch(5, erlang:length(InternalState)).\n"
  }
]