NOT RELEVANT 1. Make :- table imply :- firstorder.


DONE 2. Implement undefined predicate/method handling infrastructure.

   a. Take the intermediate repesentation of the program from the compiler.

   b. Compute the skeletons for rule heads (including facts).
      A skeleton represents a generalization of the terms in the rule heads.
      For instance, for
	  p(X)(a,Z)(b,D) :- ...
      the skeleton is 
          flapply(flapply(flapply(p,_),_,_) _, _)
      for 
          Z(X)(c,Z)(c,D) :- ...
      it is 
          flapply(flapply(flapply(_,_),_,_) _, _)
      For F-logic molecules, say,

	T[Z(X)(c,Z)(c,D) -> ...] :- ...
	Q[p(X)(a,Z)(b,D) ->> ...] :- ...

      you put into the trie the following skeletons:

	fd(_, flapply(flapply(flapply(_,_),_,_) _, _), _)
	mvd(_, flapply(flapply(flapply(p,_),_,_) _, _), _)

   c. Remove duplicates from Step (b).

   d. For each skeleton, generate a rule like:
      For each skeleton, generate a query
      ?- storage_insert_fact(storagename,Skeleton).

      Skeleton :-
	       ( storage_check_fact(storagename,Skeleton) ->
	       fail
	       ;
	       print error message (undefined predicate...),
	       abort
	       )
      This rule should be represented in the intermediate format
      and submited to the coder.

      The idea behind this rule is that if the storage area doesn't have an
      appropriate skeleton, it means that the call doesn't have a 
      rule that can possibly match it. It is a generalization of the idea
      of undefined predicates in Prolog.

   e. Need to dump the rules from Step (c) into a separate file, F.
      Name of storage should be local to the module name.

      The above file F is to be generated and/or included  ONLY if the
	  :- debug 
      directive appears in the file.
      This is because such error checking is potentially expensive to do in
      "production" runs.

      This file (F) should be included before the rules of the
      program, if the debug option is on.
      Before loading this file, need to expunge whatever is
      in the storage. (Use storage_delete_all.)
      We can probably simply add the query 
	  ?- storage_delete_all(WORKSPACE)
      at the top of the file F.



3. Module-level Encapsulation.

   GENERAL IDEA: 
       When referring to HiLog predicates in another module:
          .., p(a,Y)(X)@foo, ...
       we should translate as:
          ...,flapply'foo'exported(flapply(p,a,Y),X)

       and in module foo we should have:

          :- export p(_,_)(_)

       This should add the following fact to the export registry for module foo:
          foo'export'registry(flapply'foo'exported(flapply(p,_,_),_)).
			      ^^^^^^^^^^ - hilog translation of p(_,_)(_).

       There also will be a rule (for each HiLog arity) to connect exported
       wrappers back to the rest:

        flapply'foo'exported(HiLogPred,Arg1,...,Argn) :-
	   foo'export'registry(flapply'foo'exported(HiLogPred,Arg1,...,Argn)),
	   !,
	   flapply'foo(HiLogPred,Arg1,...,Argn).
	flapply'foo'exported(HiLogPred,Arg1,...,Argn) :-
	   issue error: pred not exported.


       Same for methods. They should be exported like:
           :- export _[method123(_,_,_) -> _]. (for all kinds of arrows)
	   :- export _:_.  (for membership)
	   :- export _::_. (for subclass)

       and the registry will contain:

           foo'export'registry(fd'foo'exported(_,method123(_,_,_),_)).
           foo'export'registry(sub'foo'exported(_,_)).
	   etc.

       We also need a patch rule for each F-logic wrapper:

           fd'foo'exported(O,Meth,Val) :-
	      foo'export'registry(fd'foo'exported(O,Meth,Val)),
	      !,
	      fd'foo(O,Meth,Val).
	   fd'foo'exported(O,Meth,Val) :-
	      issue error: method not exported


    Issue: For completely dynamic modules: need a mechanism to specify exports.
           Probably such modules should have everything exported, because
           they are created by another program.

    ASSERTING FACTS/RULES:
        Need to change the translation of insert/delete/...
	into calls to fllibinsert/fllibdelete/...
	so that the workspace is preserved. For instance, insert{a[b->c]@foo}
	should be translated into a call to fllibinsert('foo''fd'(a,b,c), foo).
	The definition of fllibinsert should then check the export registry
        to see if insert{} has been exported from module foo.


	Note: To insert{_[meth(_)->_]@foo}, both insert{} and _[meth(_)->_]
        should be exported by foo.

	Issue: make sure undefinedness checking and tabling of hilog works
	right after all these changes.

       

DONE 4. Asserting Flora rules.

   Proposal:
      - Add new update predicates like:
	    insertrule{rule,module,front/back}
	    deleterule{rule,module}

        Rules will have exactly the same syntax as Flora currently has.
	Insertion into flora(...) and prolog()/prolog(...) should not be
	allowed.
	Should check if the module we are inserting into already exists.
	By the way, we should make sure that the current predicates
	insert{...}, insertall{...}, etc., verify if the module they are
	inserting into already exists.

	We won't have backtrackable rule updates for now.


      - Add executable
		newmodule{modulename,trailertype}
        (Or should it be called flNewModule(...) and look like a regular
        predicate?)
        Should check if the module already exists.
	Trailer type can later be changed by the executable directive
	?- equality none/basic/flogic.

	Do we need
	        deletemodule{...}?

	Could be useful, especially if XSB implements garbage collection
	for atoms, since this would allow collection of atoms from large
	datasets that are no longer used.


      - Translation:
	  We will add two new kinds of wrappers: assertedA_* and assertedZ_*.
	  For F-logic wrappers fd/mvd/... we add additional rules to
	  flrcommon.fli:
	        :- dynamic assertedA_fd/3, assertedZ_fd/3.

		inferred_fd(X,Y,Z) :- assertedA_fd(X,Y,Z).
		... rules connecting inferred_* to derived_* ...
		inferred_fd(X,Y,Z) :- assertedZ_fd(X,Y,Z).

	  When insertrule{rule,module,front} is used, we implement it with
	  asserta/1. The call insertrule{rule,module,back} is implemented
	  with assertz. This way we will be able to insert rules to the
	  front and the end of the rules set.

	  Insede insertrule/deleterule, the coder should make sure that the
	  head of a predicate is translated using asserted[AZ]_* wrappers,
	  while in the body it would use the regular d_* wrappers.

      - For rules with HiLog predicates in the head, we also need another
        trailer file in the closure/ directory to hold the rules:

	        :- dynamic assertedA_HILOG_WRAP/1, assertedZ_HILOG_WRAP/1,
		   assertedA_HILOG_WRAP/2, assertedZ_HILOG_WRAP/2,
		   ....

	To make the front/back insertion work right, I think we have to add
	another wrapper for HiLog, derived_flapply, and change the
	translation so that the rule heads would contain derived_flapply.
	So the trailer might look like:

                HILOG_WRAP(X) :- assertedA_HILOG_WRAP(X).
                HILOG_WRAP(X) :- derived_HILOG_WRAP(X).
                HILOG_WRAP(X) :- assertedZ_HILOG_WRAP(X).
                HILOG_WRAP(X,Y) :- assertedA_HILOG_WRAP(X,Y).
                HILOG_WRAP(X,Y) :- derived_HILOG_WRAP(X,Y).
                HILOG_WRAP(X,Y) :- assertedZ_HILOG_WRAP(X,Y).

	Since we won't need to load the HiLog trailer more than once, we
	probably don't need the inferredHILOG_WRAP.


      - For rules with first order predicates in the head, things seem to
        be much harder. We need something similar to HiLog predicates, but
        there is a distinction between the case where we insert

		  p(...) :- ...

        and the module already has a static rule p(...) :- ...
	and the case when it doesn't.
	a. If the module has a static rule p(...) :- ...
	   then the compiler can generate the rules

	         p(...) :- assertedA_p(...)
	         p(...) :- derived_p(...)               (*)
	         p(...) :- assertedZ_p(...)

	   similarly to the way we generate the patch rules. (Again, we should
	   change the translation so that firstorder predicates in the head
	   are translated into derived_p(...) and those in the body into
	   p(...).
	b. If the module doesn't have static rules with p(...) in the head,
	   then rules of the form (*) above will have to be generated
	   *and* asserted, except that we don't need the middle rule, which
	   handles static rules that have p(...) in the head.


5. Metaprogramming

    - Need to implement the Flora analog of =.. (~..), which should work with
      different types of atomic formulas. Call it ..=.. for now (find a
      better name later). Format:

	     Atom ..=.. [Type, Module, Functor, Arity | Args]

      where Type: hlgpred, hlgterm, plgterm, flpred, ->, =>, ->>, etc.
            Module: the module of the predicate or method.
		    For hilog terms and prolog terms the module is '' (or a
		    var?).
	    Functor: the name of the predicate, functor, or method.

NOT RELEVANT 6. Implement asserting the storage-linking rules
   (the patch rules) in the
   Flora shell, so that we'll be able to use insert/delete for firstorder
   predicates in the shell.

   The way to do this is to keep track of all firstorder predicates in the
   shell.

   a. assert register_firstorder(functor/arity) into usermod.
   
   b. Check to see if functor/arity is already in main module
      (using current_predicate/1). If yes, do nothing. Otherwise,
      assert the rule:
	  functor(X,Y,...) :-
      storage_find_fact(main_module,functor(X,Y,...)).

   c. When a file is loaded into the module main, for each
      functor/arity in register_firstorder/1, do
      retractall(functor(X,Y,...)).

NOT RELEVANT 7. Implement  patch rules for firstorderall.
   Firstorderall is already implemented. We only need to add the patch
   rules.

   a. Take the intermediate results from the compiler.

   b. Collect all predicates in rule head and body in the form
      of functor/arity.

   c. Remove duplicates from Step b. Need to generate an error message
      if functor is not an atom.

   d. For each functor/arity, generate a rule like:
      functor(X,Y,...) :- storage_find_fact(current_module,functor(X,Y,...)).
      This rule should be represented in the intermediate format
      and submit to the coder.

   e. Need to dump the rules from Step d into the same file where
      program code is generated.

   There is another issue here when it comes to metaprogramming.
   When we do something like
	X ..=.. [flpred,mod,foo,5, ...]
   a patch rule for foo'mod/5 must be asserted, if it isn't already
   there.

DONE 8. If then else
    Right now if/then/else are defined in flroperator.P and syslib/flrcontrol.P
    However, the defs don't parse correctly some nested if-then-else
    expressions, such as if a then if b then c else f else g.
    Need to change the parser so that once it obtains the term constructed
    by the operators if/then/else, it would rearrange it to fix the
    associativity.

DONE 9. Add while-do, unless-do and do-until to the parser, like it is done for
   if-the-else.

DONE 10. Add the constraints syntax {...}.


DONE 11. Implement convenient versions of I/O predicates and others, such as
    new_oid(X). This module should be automatically loaded into the module
    "flora(sys)".

DONE 12. Add the symbol _@, which will be handled by the tokenizer and passed
    along to the compiler so it would insert code to replace _@ with the
    preprocessor constant FLORA_THIS_MODULE_NAME

DONE 13. Do dependency checking in the compiler to determine if a tabled
    predicate or an F-molecule depends on an update predicate.

14. Do smart reordering of arithmetic operations in rule bodies to minimize
    the possibility of errors due to unbound variables.
    Do variable analysis in delete{...}/insert{...}
    to avoid errors like in demo/aggregate.flr

	Algorithm: Bring query/\literal in update{literal|query}
		   into disjunctive normal form. For each disjunct, move
		   arithmetic expressions around to as close to the left as
		   possible subject to the restriction that the variables
		   must be bound. This requires variable analysis.
        Input: term (which includes , and ;)
	       A set of declarations like binding(op,Arity,[+,-])

15. Figure out some workaround for the tabled stuff that depends on
    dynamically asserted and deleted facts.

16. Implement the :- [+file>>module] feature, which will add rules/facts tot he
    module rather than replace it.

NOT RELEVANT 17. Provide primitives
    :- firstorder foo/1 in modname.

    This is supposed to solve two problems: 
      a. to check for declaration mismatch at the module loading time as
	  opposed to run time. 
      b. to elimitate the limitation that if a symbol, say p/2, is declared as
      	 firstorder in module foo and module bar calls p(_,_)@foo, then
         p/2 must also be declared as firstorder in bar.

    This will direct the compiler to make the right translation for things like

    ..., foo(X)@modname,...
    ..., moo(X,Y)@modname,...

    Also, the coder must dump apropriate registry records for these
    declarations in the .P file. The result would be that these
    declarations will be global to the Flora runtime environment.
    Each declaration will specify whether a particular predicate symbol is
    supposed to be first order or hilog in some particular module.

    Declarations come from explicit statements like

    :- firstorder foo/1 in modname.
    :- firstorder foo/1.

    or from implicit declarations, which come from calls like p(...)@foo.

    HiLOg declarations are always implicit.  HiLog predicate symbols are
    collected at compile time and their declarations are inserted in the
    registry.

    The "in module" version declares it for the given module, and the
    version without "in module" does it for the module in which this
    declaration occurs.

    A registry record is inserted whenever there is one of the above
    explicit or implicit declarations.  (We won't be trying to catch
    anything like X(...)@foo, because it is not clear what can be caught
    there at reasonable price).

    The global registry contains declarations like these:

    FLORA_PREFIX'symbol_declaration(
         symbol/arity,for-which-module,who-declared,firstorder/hilog)

    When a new module is loaded, we should check if there are conflicts,
    i.e., if the registry records it has conflict with the records that are
    already in the registry. For instance, if we have

      FLORA_PREFIX'symbol_declaration(p/2,foo,_,hilog)
      FLORA_PREFIX'symbol_declaration(p/2,foo,_,firstorder)

    and we are loading a module with the declaration

      FLORA_PREFIX'symbol_declaration(p/2,foo,_,firstorder)

    Also, when a module, foo, is reloaded (i.e., another program is loaded into
    that module), we should first wipe out the declarations inserted by the
    previous version of that module, i.e., we should wipe out

       FLORA_PREFIX'symbol_declaration(_,_,foo,_)

    We should also use the registry in order to decide how to translate
    symbols in the FLORA shell. If the registry has no record of the form

       FLORA_PREFIX'symbol_declaration(p/2,main,_,_)

    then p is hilog. If there is a record

       FLORA_PREFIX'symbol_declaration(p/2,main,_,firstorder)

    then it is firstorder. Such a record can be introduced by either main
    itself or by some other module.

    Another issue is what to do with subgals like

     ?- ..., literal@X, ...

     We need to check the registry at run time, when X is bound to a module
     name, to decide how to translate "literal": using hilog or first order
     translation.
    
DONE IN A BETTER WAY 18. Add a call(X) meta predicate.
    The main point right now is that

    :- p(X), X.     (*)

    won't work correctly because in Flora terms and atomic (predicate)
    formulas belong to different sorts (domains). For instance, module name
    isn't attached to the apply-wrapper for terms, but it is for predicate
    formulas.  So, f(a) in p(f(a)) is  represented as apply(f,a), while
    when it occurs in a module foo as a predicate:

    f(a).            (**)

    it is represented as apply'foo(a).
    So, the free X in (*) won't match (**).

    One solution could be to add the call/1 predicate.
    call(f(a)) would change the outermost wrapper and attach module name.
    Also, call(p) should convert to call(apply(p)), because Flora treats
    propositional constants like p as p().

DONE 19. Implement support for the full directive :- index/2
    (right now it only allows trie indexing)

DONE 20. Fix the bug that prevents a[b=>>{c,d}] and a[b*=>{c,d}].

21. Allow inheritance of procedural methods: a[*#p(...)].

DONE 22.  Right now Flora compiler collects XSB compiler options
     listed in flora_is_command_directive/1 in flrparser.P
     and then dumps them in the program as :- option.
     First, this is incorrect syntax. Should be dumping as
     compiler_options([option,option,...]).
     Second, this doesn't have any effect because in flrutils.P we invoke
     XSB compiler using the options spec_repr, ti_all, optimize.

     What is needed is that the compiler collect all these XSB options,
     and then add the default options that don't contradict the explicitly
     specified ones (plus xpp_on). Then the coder would dump
     :- compiler_options([option,option,...]) into the .P file.

23.  Make the compiler dump the original source in comments right
     in front of the translated code block.

DONE 24.  Implement a richer anonymous oid syntax.
     In addition to _#, allow _#1, _#2, etc. Tokenizer needs to be updated
     to allow that.
     
     The idea is that two occurrences of, say, _#2 within the same rule
     would be assigned the same oid and _#1,_#2, _# would be different.
     Also, occurrences of _#1 across different rules would be different as
     well.

     The schema is simple. First, numbered (_#1, _#2) etc and unnumbered
     (_#) oids should use difference naming schemas. The numbered oids can
     use, say, _$_$_flora_newoid<rule-number>|<oid-number>.
     For instance, _#345 that appears in the clause number 9876 would be
     replaced with _$_$_flora_newoid9876|345.

     We should also check that each numbered oid that occurs inside a rule
     is referenced there at least twice and issue a warning if not.
     This can be done by asserting
     ruleoid(345,1)
     when the compiler sees _#345 within the clause 9876 the first time.
     While processing that rule, the compiler would increment the count.
     For instance, in our case it would retract the above fact and assert
     ruleoid(345,2)

     When it is done with the rule, it should check if there are facts of
     the form ruleoid(_,1) and issue an error if there are.  The ruleoid/2
     relation is reset by the compiler at the beginning of each new rule.

25. Do the right thing when negation is applied to a formula that has a
    mix of procedural and tabled things, and which has both
    conjunctions and disjunctions.
    Should we allow control constructs, such as if-then-else?
    Probably this should be a job for the parser to check that control
    constructs don't appear under the skope of \+ or tnot.

DONE 26. Implement @prologall() and @prologall(module).
    They should behave the same way as @prolog(...), but the coder should
    dump the code differently.
    For instance, p(X,Y,Z)@prolog() dumps it as p(X,Y,Z), while
    p(X,Y,Z)@prologall() should dump it as
    
    (var(X),! ; flP2H(_newvar1234,X)),
    (var(Y),! ; flP2H(_newvar1235,Y)),
    (var(Z),! ; flP2H(_newvar1236,Z)),
    p(_newvar1234,_newvar1235,_newvar1236),
    (nonvar(X),! ; flP2H(_newvar1234,X)),
    (nonvar(Y),! ; flP2H(_newvar1235,Y)),
    (nonvar(Z),! ; flP2H(_newvar1236,Z))

27. Implement the database interface for Flora. The issue is how to save
    object molecules transparently, i.e., an atom like
    a[b->c,e->>d] in a database and allow it to be queries.

    The database should probably be somehow associated with a module, so to
    save stuff we would use

    insert{a[b->c,e->>d]}@dbmodule

    To query: X[b->Y, Z->>d]@dbmodule.

    Probably need a command like

    ?- connect(database-url, flora-module)
