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. Encapsulation.

   GENERAL IDEA: 
       When referring to Flora predicates in another module, e.g., 
	   p(X)@foo
       translate as:
           ...,p'foo'exported(X)
       In module foo, p/1 must be declared as
           :- export p/1.

       Which would insert the rule

           p'foo'exported(X) :- p'foo(X).

       Same for methods.
       Should have something like:
           :- export method123/5 ->. (for all kinds of arrows)
	   :- export :.  (for membership)
	   :- export ::. (for subclass)

       For hilog predicates:
          p(a,Y)(X)@foo
       means:
          ...,flapply'foo'export(flapply(p,a,Y),X)
       and in foo we should have:

          :- export p(_,_)/1.

       which adds the fact
          foo'exported'hilog'registry(flapply(p,_,_)).
			              ^^^^^^^^^^ - hilog translation of p(_,_).
       There also will be a rule:
          flapply'foo'exported(HiLogPred,Arg) :-
			foo'exported'hilog'registry(HiLogPred),
			flapply'foo(HiLogPred,Arg).
    ISSUES:
       - What about meta programming?
         ..., X(...)@foo, ...
	 Here X shouldn't range over hilog predicates that aren't exported.
	 Likewise,
	 ..., a[ X(...) -> ...]@foo, ...
	 should not bind X to non-exported methods.
	 Probably the same HiLog's trick with registry will work.

      - What about asserting?
        ..., insert{p(a)@foo}, ...

	What if p/1 is not exported in foo?
	One solution: in debug mode insert should check the registry of
	exported things in the module foo.

    More fine-grained encapsulation based on the ideas from annotated logic.
       

4. Asserting Flora rules.

   Proposal:
      - Allow assertion only into modules that are declared as 
        :- dynamicmodule
	(in the file loaded into that module).

      - The dynamicmodule directive should tell the compiler that only
	directives are allowed in that paticular file.

      - The rules connecting the storage tries (the patch rules)
        of the form

	  p(X) :- storage_find_fact(p(X),_).

	for firstorder predicates, hilog and F-logic wrappers must be
	asserted into the dynamic modules (but the trailer can be compiled
	and appended).

	For the Flora rules we don't need to change the translation much.
	We assert
	   derived_fd'foo(X,Y,Z) :- ....
	We should also add to the trailer (of the dynamic modules) the 
	appropriate declarations of the form
	   :- dynamic derived_fd'foo/3.
	   .....
	Since these predicates occur only in the rule bodies in the
	trailer, we are safe from clashes with static predicates.

	To enable the current parser parse the rules inside
	insert{...} correctly, we have to give the following argument
	definition for ':-'

	:- arguments ':-'(hform,bform).

	where "bform" is the existing argument type and "hform" needs to be
	added. The effect of "hform" is to force the compiler to compile
	the head of the rule as a list of formulas rather than an oid term.

	Or, maybe, the compiler should just undertand that :- is a special
	predicate and its first argument is the rule head. So, things must
	be translated differently there.
	Right now if we have
	:- arguments p(bform).
	p(a[b->c]) :- ...
	then a[b->c] is translated as defived_fd, so the compiler treats
	bform in the rule head differently. We should extend this treatment
	to the predicate ':-'.

	Another idea: use `meta' instead of `bform'.

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.

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,...)).

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.

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.

9. Add the contraints syntax {...}.


DONE 10. 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)".

11. 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_MODULE.
    When compiling, the macro definition
    #define FLORA_MODULE  .....
    would be dumped into the .P file

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

13. 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,[+,-])

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

15. Implement the :- database directive, which will direct the compiler to
    not include the patch rules and to disallow real rules (as opposed to
    just facts in the file).
    In conjunction with this, do the following in the parser:
       1. Ensure that directives are allowed only at the top of the file.
          Have a flag, clause, which is conset to 0. When the first
	  non-directive is encountered, conset it to 1.
	  If a directive is encountered after that---issue an error.
       2. Ensure that :- database occurs before any :- firstorder or :-
	  hilog directive. If one of these directives is encountered,
	  set the nodatabase flag. If :- directive is encountered after
	  that, issue an error.
       3. If :- database is encountered, set the database flag.
	  The compiler should check this flag to decide whether to dump the
	  patch rules and for deciding on the error checking.

16. Provide primitives
    :- firstorder foo/1 in modname.
    :- hilog moo/2 in modname.
    (For symmetry, let us also have :- hilog moo/2. without the module.
    All this is supposed to do is to check if there is a conflicting
    declaration.)

    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 code to preserve 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.
    When the shell runs, it would know how to translate predicate literals
    that are entered on command line.

    The global declarations should be something like:

    FLORA_PREFIX'decl(symbol,firstorder/hilog,ownermodule,consumercount)

    When a new module is loaded, we should check if there are conflicts.
    (A conflict can be complex and involve default definitions, etc.)
    We should decide if we will allow a module to redefine the
    declarations it owns when the module is reloaded. But if we do allow
    this, this can be done only if there are no consumers for the symbol.
    
17. 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().

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

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

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

21.  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.

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

DONE 23.  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.

!24. Make @prolog() have scope like any other @module, including overriding
    by declarations in the subscope, etc.
