 

    An Introduction to Coral's Interface with C++
    ------------------------------------------

    For those interested in writing C++ programs that use the
    Coral library, we provide the following reference to help them
    get started.  We have also provided some sample programs to 
    demonstrate the use of these functions.


    Table of Contents                                        Line
    -----------------                                       ------
 
    Introduction                                               25
    Using Coral's C++ Interface                                36
    Discussion of Sample Programs                              59 
    Embedded Coral (and using the translator)                  72
    List of Coral C++ functions and methods for Coral types   127
    Incrementally Loading Programs into Coral                 609 
    Using Coral with Tk/Tcl (coralsh)                         615 
    


    Introduction
    ------------
    Coral provides an interface to C++ to allow those users who wish
    to use the Coral Database within their own programs.  This can be
    done using Coral's embedded mode, which allows Coral code to appear
    inside of your C++ program the same as it would appear at the Coral
    prompt.  For more speed and flexibility, Coral's C++ interface can
    be used directly.  Most programs use a mixture of these two approaches
    as appropriate for their needs.
    

    Using Coral's C++ Interface
    ---------------------------
    The classes, functions and methods considered to be in Coral's C++
    interface are described later in this reference.  The functions
    listed are the ones that we are willing to half-heartedly commit
    to not changing the interface to in the near future.  If you are
    interested in portability to future versions of Coral, you should
    attempt to limit yourself to these operations whenever possible.

    A C++ program using Coral should call init_coral() before attempting
    any operations related to Coral, and exit_coral() when finished.
    The prototypes for these functions are given later in this reference.
    For most of the sample Coral C++ programs these functions are simply
    called at the beginning and end of main().

    Unless specifically mentioned otherwise, all functions in this 
    document that return a pointer expect you to delete the pointer
    when you are finished with it.  For complex objects, there
    is some structure sharing, but it is handled internally via
    reference counting, so deleting the pointer is always
    'The Right Thing To Do'.

    
    Discussion of Sample Programs (and using the translator)
    --------------------------------------------------------
    The sample programs are at programs/examples/C++

    The examples are all '.S' files, which require the translator
    to convert them to C++.  There is also a Makefile which shows
    how to compile these into executables.

    The examples demonstrate embedding coral into a C++ program,
    passing parameters from C++ to Coral, and scanning Coral relations
    from C++.


    Embedded Coral
    --------------
    Declarative Coral code can also appear directly inside your C++
    program, we refer to this as Embedded Coral. To use this mode,
    you should call init_coral() at the beginning of main() and
    exit_coral() at the end.  You may then simply include the embedded
    Coral code by surrounding it with the embedding brackets '\[' and '\]'. 

    For example:
        \[
            data(2,3).
            data(foo,9.2).
           ?data(X,Y).
        \]

    Is a valid section of a C++ program that will result in the relation
    data(arity 2) being defined, inserting the facts shown, and listing
    the bindings for the query on stdout.

    The transformation to valid C++ code is performed by a program 
    called the 'translator' that is included in the Coral distribution.
    The sample Makefile included in the C++ Interface directory 
    demonstrates  the proper use of the translator. Generally, files
    containing Embedded Coral are suffixed with '.S', from which the
    translator then generates a '.C' file with the same base name. 

    Embedded Coral allows certain C++ types to be passed into the embedded
    section as arguments.  For the proper type of the object to be
    known, the type must be supplied in a special cast. Plese note that the
    paranthesis around the type, as well as the dollar signs, are required.
     
    For example:
        int j = 2;
        double r = 9.2;
        char *name = "foo";
        \[
            data( ($int) $j, 3).
            data( ($string) $name, ($double) $r).
          ? data(X,Y).
        \]

    The currently allowed types, and the appropriate parameter casts are
    given by the following table:

      Cast                    Equivalent C++ Type
      ----                    -------------------
      $int                    int
      $double                 double
      $string or $char*       char*
      $CArg* or $Cor_CArg*    Cor_CArg*
      $chunk or $void*        A pointer to anything.

      (see the param?.S example programs for examples of usage)


    List of Coral C++ functions and methods for Coral types
    -------------------------------------------------------

    This section discusses the function available to a programmer
    using the Coral C++ interface. It also lists the major coral
    types visible from the C++ interface, and their more useful methods.
    In many cases, there are functions available from the interface
    that are exact parallels to methods available for the appropriate
    class; this is simply our attempt to be hip by making the interface
    more object-oriented, the older functions remain for backward
    compatibilty.


      Type                                        Line
      ----                                       ------
      Cor_CArg                                     151
      Cor_CArgStack                                311
      Cor_ArgList                                  360
      Cor_Tuple                                    421
      Cor_Relation                                 459
      Cor_ScanDesc                                 510
      Miscellaneous Functions                      543


    Cor_CArg:
    ----------

    A CArg is a coral argument. It can hold a number, string, list, set
    or functor (a fact), it can also be empty.

    The constructors/destructor for CArg:
        Cor_CArg(void);
        Cor_CArg(const Cor_CArg& a);
        Cor_CArg(int n);
        Cor_CArg(double d);
        Cor_CArg(const char *name);
       ~Cor_CArg();

        Cor_CArg *make_arg  (char *name);
        Cor_CArg *make_arg  (Cor_CArg& name);

    For creating a CArg that holds a functor term (ie 'rel(foo,2,bar)'.)
        Cor_CArg *make_arg  (char *func_name, Cor_ArgList *args);

    These functions create CArg's that store a Coral variable. The var_num
    parameter uniquely identifies a variable; variables with the same
    var_num are considered the same.  'print_name' is the name that
    will be shown if this variable is printed, it is not used internally.

        Cor_CArg *make_var  (int var_num);
        Cor_CArg *make_var  (char *print_name, int var_num);
        Cor_CArg *make_var  (Cor_CArg *print_name, int var_num);


    This empties out the current contents of a CArg,
    returning it to an empty state.
        void Cor_CArg::init();

    These methods set a new value (and type) for a CArg. 
        Cor_CArg& Cor_CArg::operator= (const Cor_CArg& a);
        Cor_CArg& Cor_CArg::operator= (int i);
        Cor_CArg& Cor_CArg::operator= (double d);
        void Cor_CArg::set_num(int ival);
        void Cor_CArg::set_num(double dval);
        void Cor_CArg::set_chunk(void *chnk);

    A method for printing a CArg onto a stream. This method will quote
    the CArg if it contains any whitespace, special characters, or
    starts with a capital letter or digit. (To print without these
    quotes, print the char* returned by 'carg.symbol()'.)
        friend ostream& operator<< (ostream& out, const Cor_CArg& carg);

    This method tests if a CArg is empty, as it would be after an init().
        int Cor_CArg::is_empty() const;

    Tests to see if two CArgs are equal.
        int Cor_CArg::equals(const Cor_CArg& arg2) const;
        int Cor_CArg::equals(char *str) const;

    This method returns the type of object that is stored in this CArg.
    The enumerated type definition is also shown below.
    There are also methods to test for a specific type.

        CArgKind Cor_CArg::Kind() const;

        enum CArgKind {
            EMPTY_ARG,     // Empty
            INT_ARG,       // An integer
            DOUBLE_ARG,    // A double
            SYMBOL_ARG,    // A symbol (char *)
            OTHER_ARG,     // A complex type (set, list, functor, etc)
            CHUNK_ARG      // A pointer to a chunk of memory
        };

        int Cor_CArg::is_num() const;
        int Cor_CArg::isConstant() const;

        int Cor_CArg::is_int()    const;
        int Cor_CArg::is_short()  const;
        int Cor_CArg::is_long()   const;
        int Cor_CArg::is_float()  const;
        int Cor_CArg::is_double() const;
        int Cor_CArg::is_string() const;
        int Cor_CArg::is_symbol() const;
        int Cor_CArg::is_chunk()  const;


        int is_int    (const Cor_CArg& c);
        int is_long   (const Cor_CArg& c);
        int is_short  (const Cor_CArg& c);
        int is_float  (const Cor_CArg& c);
        int is_double (const Cor_CArg& c);

        int is_symbol (const Cor_CArg& c);
        int is_string (const Cor_CArg& c);
        int is_chunk  (const Cor_CArg& c);

        int is_num      (const Cor_CArg& c);
        int is_constant (const Cor_CArg& c);

        int is_var      (const Cor_CArg& c);
        int is_functor  (const Cor_CArg& c);
        int is_nil      (const Cor_CArg& c);
        int is_list     (const Cor_CArg& c);

    These methods return the value of a CArg, they do no error
    checking, assuming that you have the type right. 
        double Cor_CArg::NumDval() const;
        int    Cor_CArg::NumIval() const;

    Returns the symbol stored and its length, they do no error checking.
        char  *Cor_CArg::symbol() const;
        int    Cor_CArg::symlen() const; 

    Returns the chunk stored:
        void  *Cor_CArg::chunk();

    Functions to extract the info from a CArg (no error checking is done).
        int    make_int     (const Cor_CArg& c);
        short  make_short   (const Cor_CArg& c);
        long   make_long    (const Cor_CArg& c);
        float  make_float   (const Cor_CArg& c);
        double make_double  (const Cor_CArg& c);
        char  *make_string  (const Cor_CArg& c);

        char *functor_name  (const Cor_CArg& c);
        Cor_ArgList *functor_args (const Cor_CArg& c);


    These functions create/operate on Coral lists (ie: '[a,b,c]')

      Creates a new empty list.
        Cor_CArg  *make_nil  (void);

      Adds the CArg 'car' to the front of the list 'cdr'.
        Cor_CArg  *make_cons (const Cor_CArg& car, const Cor_CArg& cdr);

      Creates a new list from a variable list of CArg's given.
      All items in the vararg list should be of type 'Cor_CArg*'.
        Cor_CArg  *make_list (int num_arg, ...);

    Ex: 
        Cor_CArg *two = new Cor_CArg(2);
        Cor_CArg *pi  = new Cor_CArg(3.14);
        Cor_CArg *foo = new Cor_CArg("foo");

        Cor_CArg *list = make_list( 3, two, foo, pi );

        Now 'list' contains the Coral list '[2,foo,3.14]'

      Returns the length of this list.
        int list_length( Cor_CArg& list );

      Returns the car and cdr of the list given. For those not 
      familar with Lisp, 'car' is the first element of the list,
      while 'cdr' is the list without the first element. 
        Cor_CArg *make_car (const Cor_CArg& list);
        Cor_CArg *make_cdr (const Cor_CArg& list);
   
      Functions to test if a CArg is a list, and if it is nil.
        int is_nil (const Cor_CArg& c);
        int is_list (const Cor_CArg& c);


    Cor_CArgStack:
    ---------------

    A CArgStack is a dynamic stack for holding pointers to CArg's, it
    can also be considered an array by indexing into it using the 
    get_ith(), dup_ith() methods.

    The constructors/destructor for CArgStack:
        Cor_CArgStack(int dp=1);
       ~Cor_CArgStack();

    A method for printing a CArgStack onto a stream. The CArgs in the
    stack are printed out seperated by commas. (printed in FIFO order)
        friend ostream& operator<< (ostream& out, const Cor_CArgStack& ca_list);

    Add a CArg to the stack
        void Cor_CArgStack::push(Cor_CArg*);

    Returns the current number of CArgs stored.     
        int  Cor_CArgStack::count();

    Gets a pointer to the ith element of the stack, leaving the element there. 
    (counts from 0 being the first element inserted.)
        Cor_CArg *Cor_CArgStack::get_ith(int i);

    Gets a _copy_ of the ith element of the stack, leaving the element there. 
    (counts from 0 being the first element inserted.)
        Cor_CArg *Cor_CArgStack::dup_ith(int i);

    Removes the last element from the stack and returns it.
        Cor_CArg *Cor_CArgStack::pop();

    Copies the contents of a CArgStack to another (duplicating all elements)
        void Cor_CArgStack::copy(Cor_CArgStack&);

    Fills the ArgList given with the contents of the CArgStack, emptying
    the CArgStack in the process.
        void Cor_CArgStack::build_arglist(Cor_ArgList& args);

    Empties out the stack - deleting each element.
        void Cor_CArgStack::empty();

    Checks if the stack is empty.
        void Cor_CArgStack::is_empty();

    Duplicate the stack (and all elements).
        Cor_CArgStack *Cor_CArgStack::dup();


    Cor_ArgList:
    -------------

    An ArgList stores coral argument lists.

    The constructors/destructor for ArgList:
        Cor_ArgList(int size);
        Cor_ArgList(const Cor_ArgList &);
        Cor_ArgList();
       ~Cor_ArgList();

        void Cor_ArgList::operator=(const Cor_ArgList&);
        int Cor_ArgList::count() const;
        int Cor_ArgList::arity() const;

        Cor_CArg& Cor_ArgList::operator[] (int i) const;

        const Cor_CArg& Cor_ArgList::arg(int i) const;

    Returns true if all the arguments are NumArgs or Symbols
        int Cor_ArgList::isConstant();

    Methods for printing an ArgList onto a stream. The CArgs in the
    arglist are printed out seperated by commas.
        friend ostream& operator<< (ostream& out, const Cor_ArgList& al);
        void Cor_ArgList::printon(ostream *file) const;

    Make a duplicate of this ArgList.
        Cor_ArgList *Cor_ArgList::dup();


    Creates an ArgList with the CArgs specified.
    All items in vararg list should be of type 'Cor_CArg*'
        Cor_ArgList *make_arglist (int len, ...);

    A destructive version of the above (deletes arguments).
    This call is useful to avoid temporary variables, as
    you can imbed the calls to make_arg().
        Cor_ArgList *make_arglist_d (int len, ...);

    Ex.
      Cor_ArgList *al = make_arglist_d(2, make_arg("one"), make_arg("two"));

    Versions which take CArg references instead. References cannot
    be passed through '...' but these three versions allow 
    ArgLists to be created with 1, 2, or 3 CArg references. 
        Cor_ArgList *make_arglist (const Cor_CArg& a1);
        Cor_ArgList *make_arglist (const Cor_CArg& a1, const Cor_CArg& a2);
        Cor_ArgList *make_arglist (const Cor_CArg& a1, const Cor_CArg& a2,
                               const Cor_CArg& a3);

    Concatenates two ArgLists into a new one.  The new ArgList
    created does not rely on the continued existance of its 
    constituent ArgList's (they can be deleted).
        Cor_ArgList *concat_arglists (Cor_ArgList *al1, Cor_ArgList *al2);

    Creates an ArgList of the length specified, with all arguments
    being unique variables.
        Cor_ArgList *make_vararglist (int n);


    Cor_Tuple:
    -----------

    A Tuple is an ArgList with some extra information about which 
    variables are free/bound.

    The constructors/destructor for Tuple:
        Cor_Tuple()
        Cor_Tuple(int arity);
        Cor_Tuple(Cor_ArgList& a);
        Cor_Tuple(Cor_ArgList *arglist);
       ~Cor_Tuple();

        Cor_Tuple *make_tuple(int arity);
        Cor_Tuple *make_tuple(Cor_ArgList *arglist);

    Returns true if all variables are free.
        int Cor_Tuple::default_bindenv() const;

    Returns true if all arguments are ground (bound).
        int Cor_Tuple::isConstant();

        void Cor_Tuple::do_delete();
        int Cor_Tuple::is_deleted(); 
        Cor_ArgList& Cor_Tuple::args();
        int Cor_Tuple::arity() const;

        Cor_CArg& Cor_Tuple::arg(int i) const;

        Cor_CArg& Cor_Tuple::operator[] (int i) const;
        void update_tuple (Cor_Tuple *tuple, int arg_pos, Cor_CArg& new_val);

    Methods for printing a Tuple onto a stream. The CArgs in the
    tuple's arglist are printed out seperated by commas.
        friend ostream& operator<< (ostream& out, const Cor_Tuple& tuple);
        void Cor_Tuple::printon(ostream *file) const;

    
    Cor_Relation:
    --------------

        Cor_Relation( int arity, int delta_indexed = -1 );
        Cor_Relation();

        int Cor_Relation::arity() const;

        void Cor_Relation::print_name(ostream *file);
        int Cor_Relation::isConstant();
        int Cor_Relation::tuple_count();
        void Cor_Relation::printon(ostream *file) const;
        void Cor_Relation::printon(ostream *file, char *) const;
        void Cor_Relation::print_facts(ostream *file,
            Cor_ArgList *arglist = NULL, int as_table=0) const;

        int Cor_Relation::insert_tuple(Cor_Tuple *tuple) = 0;

    Empty tuples out of the relation.  Delete the tuples
    only if the deleteTuples arg is not 0.
        void Cor_Relation::empty_relation(int deleteTuples = 0);

        int Cor_Relation::tuple_delete(Cor_Tuple *tuple);

        int Cor_Relation::tuple_insert(Cor_Tuple *tuple);

        int Cor_Relation::tuple_update(Cor_Tuple *tuple_old,
                Cor_Tuple *tuple_new);

        void update_tuple (Cor_Relation *rel, Cor_Tuple *old_tuple,
                Cor_Tuple *new_tuple);

        void delete_id_tuple (Cor_Relation *rel, Cor_Tuple *tuple);
        void delete_tuple (Cor_Relation *rel, Cor_Tuple *tuple);

        Cor_Relation *make_rel(char *rel_name, int arity);

        Cor_Relation *find_relation (char *db_rel_name, int arity);

    Some _macros_ to simply moving through a Relation (without a Cor_ScanDesc,
    see next section on Cor_ScanDesc to perform a scan.)
    
        FOR_EACH_TUPLE(Cor_Tuple *tuple, Cor_Relation *rel)

        FOR_EACH_MATCHING_TUPLE(Cor_Tuple *tuple, Cor_Relation *rel,
                Cor_Tuple *match_tuple)

        END_EACH_TUPLE(Cor_Tuple *tuple);



    Cor_ScanDesc:
    --------------

    The ScanDesc class provides the facility of scans over coral relations.

        Cor_ScanDesc(Cor_Relation *rel);
        Cor_ScanDesc(Cor_Relation *rel, Cor_Tuple *match_tuple);
       ~Cor_ScanDesc();

        Cor_Tuple *Cor_ScanDesc::next_tuple();
        int Cor_ScanDesc::no_match();


    Cor_ScanDesc *open_scan( char *query );    // NEW!

        Use the query in 'query' to find a relation, and open a
    scan on that relation, using the form (again from 'query') to
    specify the tuples which will match. The query should appear
    the same as it would from the Coral prompt, with a few exceptions.
    If the relation isn't found, or Coral can't parse a fact from the
    string given, NULL is returned.

        1) No expressions (unary minus is okay. ie '-3')
        2) There must not be a space between a functor's name and
           the starting parenthesis of its argument list. The relation
           name may not be quoted.

    Ex:
        Cor_ScanDesc *sd;

        sd = open_scan( "myrel(2,X,Y,[3,X,1])" );


    Miscellaneous Functions
    -----------------------

    Initialize Coral. This call should be done at the beginning of main()
    to initialize Coral. 
        void init_coral(char *program_name);


    To shutdown Coral.
        void exit_coral(void);


    To parse a single fact from a buffer. (See the restrictions
    listed with the open_scan() function.) 
        Cor_Tuple *Cor_parseFact(char *fact_buff,
                    Cor_CArg& rel_name, int *arity=NULL);



    The query is a tuple for the relation, and any facts in the
    relation that unify with the query tuple are answers to the query.
    For example, (X,Y) is a query that returns all tuples in a binary
    relation.  Similarly, (1,Y) returns all tuples that have a 1 in the
    first column.  It adds the answer tuples to the relation result.
    If the result parameter is NULL, a new relation is allocated and
    the result points to it.
    Returns:  The number of answer tuples.  A result < 0 implies error.

        int call_coral(char *exp_pred_name, Cor_Tuple *query,
                Cor_Relation *&result);


    Relation *queries must contain queries on the relation.
    It adds the answer tuples to the relation result.
    If the result parameter is NULL, a new relation is allocated
    and result points to it.
    Returns:  The number of answer tuples.  A result < 0 implies error.

        int call_coral(char *exp_pred_name, Cor_Relation *queries,
                  Cor_Relation *&result);


    Interface functions for calling the imperative module:

    The user needs to write a routine with signature

    Cor_Relation *pred_solver (Cor_Tuple *query);
      -or-
    Cor_Tuple *pred_solver (Cor_Tuple *query);

    for the predicate `pred', and add a declaration matching the form:

    int add_builtin (char *pred, int arity, UserRelProc pred_solver);
      -or-
    int add_builtin (char *pred, int arity, UserTupleProc pred_solver);
    
    where `arity' is the arity of the relation named by `pred'.

        int add_builtin (char *pred, int arity, UserRelProc pred_solver);
        int add_builtin (char *pred, int arity, UserTupleProc pred_solver);

    Macros to return, indicating failure.
        BUILTIN_FAIL_RETURN          (returns int)
        VOID_BUILTIN_FAIL_RETURN     (returns void)


    Incrementally Loading Programs into Coral
    -----------------------------------------

    Incremental Loading is not currently operational.


    Using Coral with Tk/Tcl (coralsh) 
    ---------------------------------

    The debugging/query explanation tool 'Explain' is written in Tk/Tcl
    with a shell extended to provide coral commands. This shell, 'coralsh',
    is created by a normal make of the program (or comes precompiled with
    the precompiled versions).  The commands added to the shell are
    documented here so that it can be used independently.

    The shell 'coralsh' is actually the combination of TkX/TclX, Coral,
    and 'treesh', a Tk/Tcl Tree Widget written by Allan Brighton.
    Needless to say, I will only explain the commands created by Coral
    here, for information about the abilities/usage of TkX/TclX or
    the Tree Widget you will need to consult their documentation.  

    There are 13 commands added to the shell by coral, or actually one
    command ("coral") with 13 sub-commands.  These commands were
    written to provide the necessary hooks to implement 'Explain' in Tcl.
    Note that the subcommand 'parse' provides an ability similar to the
    embedded mode in C++.

    coral init ?program_name?


    coral exit


    coral consult file ?file?          Consult 1 or more files.


    coral open coral_query


    coral close scan_id


    coral get_tuple scan_id ?-dispose? ?-args? ?list?


    coral sprint tuple_id            "Prints" the item specified to
    coral sprint arg_id              the normal result string.


    coral arg tuple_id index          Returns arg_id


    coral delete arg_id ?arg_id...?       Deletes the space allocated
    coral delete tuple_id ?tuple_id...?   for these tuples and args.

                                    
    coral ident arg_id                Returns type of arg (one of:
                                          empty, int, double, string,
                                          list, functor or chunk)


    coral tcl_list ?-args? arg_id     Returns coral list of arg_id
                                          as a tcl list


    coral parse string ?string?       Parse the string as coral input



    coral list_rels                   List out the currently defined relations.

