DOCUMENTATION FOR THE TRANSLATOR (CORAL : IMPERATIVE MODULE) -----------------------------------------------------------The translator accepts the following options -i -o -e -c inputfile for the outputfile for the errormsgsfile for the error coralfile for the input file output file messages declarative code The default for each of these is stderr. In addition, -options lists the current options available. Currently, the user can have 1) export declarations 2) declarative code 3) make_tuple function in the C++ module. The functionality of each of these is discussed below. 1) EXPORT DECLARATION : Export declaration lets the user call C++ code form the declarative code. An export declaration when translated generates a solver function for the relation and a dummy function to load this relation. The export declaration can be used anywhere in the input module, except in the middle of a function. It also has to appear on a new line. An export declaration is similar to an extern declaration, with extern replaced by export. A typical export declaration might look like export int myfunc(int *, ....); Here, the first "int" refers to the type returned by the function "myfunc" for which the solver is being generated. The list of arguments which the function takes follow the function name. Consider the following scenario : The user is writing declarative code, and feels the need to do some complex computation. In a C++ Module, the user would just write the function (lets say "myfunc") and call it. However, in order to use "myfunc" in a declarative module, it has to be entered as a relation. With the help of an export declaration, the user would write the function "myfunc", make an export declaration, and run the translator on the module. The following example illustrates this point. // input program #include <stdio.h> export double myfunc(double); double myfunc(double x) { return x; } The output produced is #include <stdio.h> #include <strings.h> #include "coral-includes.h" long temp__11; extern void temp__12(); extern double myfunc(double ); static Tuple * myfuncsolver(Tuple *query) { if (query == NULL) { fprintf(stderr, "Null argument passed to myfuncsolver \n"); return NULL; } int arity = query->arity(); ArgList *alist = ArgList::New(arity); (*alist)[0] = (query->args())[0]; double arg0 ; arg0 = (double)make_double((query->args())[0]); double retvalue ; retvalue = myfunc(arg0); (*alist)[1] = make_arg(retvalue); Tuple *return_tuple = new Tuple(alist); return return_tuple; } double myfunc(double x) { return x; } void temp__12() { BuiltinUserTupleRelation *temp__13; temp__13 = new BuiltinUserTupleRelation(2, EnterSymbol("myfunc"), myfuncsolver); } The user can load the compiled version using load(filename.o). Then the following query can be executed : ?myfunc(3.0, Ans). 2) The export decalaration lets a user call C++ code from declarative module. Sometimes need arises to call declarative code from a C++ module. At times, it is just more convenient to call declarative code from the C++ routine. If, for example, the user has to initailise a base relation with 1000 entries, one can simply put the following stmt in the C++ module. for (int i = 0; i< 1000; i++) { \[ rows($i). \] } Of course, there is an overhead for this convenience - namely writing to a file everytime through the loop. Maybe, for such a small example, this should never be done. This example just demonstrates the functionality available to the user. The \[ and \] demarcate the declarative code. Any variable within these is treated as a coral variable unless it is preceded by a $ sign. The $ signifies a C++ variable, whose runtime value is used. Currently, these variables can be any of the following types : char, char *, float, double, int. Lets say there is a relation "emp" in the database. Salaries have to be updated depending upon the number of people working for each person. The user can simply write the coral module inside the routine declaring the relation "numofemps", as shown below. void Update_Sals(Relation *emp) { \[ module Employee. export numofemps(bf). worksfor(E,M) :emp(E,M,S). worksfor(E,M) :worksfor(E,E1), emp(E1,M,S). numofemps(M, count(set(<E>))) :- worksfor(E,M). end_module. \] Relation *numofemps = new Relation; Tuple *query = make_tuple("X,Y"); call_coral("numofemps", query, numofemps); // more code follows } This example also illustrates the use of make_tuple.