; File: oaa-perl.doc ; Purpose: Documentation for OAA 1.0 Perl Library ; Author: Adam Cheyer ; Updated: 10/15/99 The Perl OAA library is very similar to the C version. The primary differences are: - Naming: The prefix "oaa_" has been added to all function names in Perl to avoid possible naming conflicts. All function names are also listed in lowercase, whereas in C, this was not consistent. - C library functions usually return values in an argument that must be deallocated after use. Perl functions simply return values as the value of a function. Example: C: char *elt; NthElt("1,2,3", 2, &elt); use(elt); OAA_Free(elt); Perl: my $elt; use(oaa_nth_elt("1,2,3"), 2); Here is an example of a sample Perl agent. #!/opt/perl/released/bin/perl -w # include OAA library use OAA; # do_event: user-defined callback to handle incoming # requests and messages. # args: # $ks: contains ID of requesting agent # $func $args: contains event $func($args) # returns: # do_event should return a list of answers to the # query, or the empty list if none found. sub do_event { my ($ks, $func, $args) = @_; my $arity = oaa_list_len($args); my $answers = "[]"; # a(X) if (($func eq "a") && ($arity == 1)) { my $ans = oaa_solve("b(X)", "[]"); $answers = "[a($ans)]"; } return $answers; } # app_done: an opportunity to clean up anything before # the agent exits (as a result of a "halt" message). sub app_done { print "In APP_DONE!\n"; } # main: should connect to the Facilitator and then wait for # incoming messages. sub main { my ($host, $port); # Looks up host and port from environment vars, cmd line or setup file ($host, $port) = oaa_find_host_port(); # Connects to facilitator, registering name and solvables oaa_setup_communication("test", $host, $port, "[a(X)]"); # Waits for events oaa_loop(1); # 1 = "Print 'ready', 2 = "Don't print" } main(); ######### LIBRARY REFERENCE DOCUMENTATION # /**************************************************************************** # * name: oaa_find_host_port # * purpose: Finds host and port by looking on command line, env # * vars, and setup file (in that order of priority). # * returns: # * - ($host, $port) # * example: # * ($host, $port) = oaa_find_host_port(); # ****************************************************************************/ # **************************************************************************** # * name: oaa_setup_communication # * purpose: Establishes tcp connections to the Server and registers agent # * inputs: # * - char *KS: Name for the KS # * - char *host: host to connect to # * - int port: port to connect to # * - char *Solvable: Prolog-formatted list of solvables provided by the KS # * return value: TRUE if connection made; exits otherwise # * example: # * oaa_setup_communication("myagent", "trestle", 3366, "[a(X)]"); # ****************************************************************************/ # **************************************************************************** # * name: oaa_disconnect # * purpose: Disconnects client from Facilitator # **************************************************************************** # **************************************************************************** # * name: oaa_delay_solution(Id) # * purpose: Defer solving a do_event request until a later time. # * This procedure should be called in do_event() when a programmer # * wants to return from do_event() without returning an immediate # * solution. "answers" will be given an appropriate variable, and # * an ID is returned by this function, which should be used to call # * oaa_return_delayed_solutions(Id,Solutions) when ready. # * inputs: # * In C, oaa_delay_solution calculates an ID automatically. In # * this perl library, we ask the user to pass in an identifier # * that represents the solution that is delayed. This ID will # * later be used to return solutions to the delayed task, when ready. # * returns: # * returns an appropriate result such that answers can be deferred until # * a later time. # * implementation: # * answers will contain "DELAY_PRED(i)": since usually answers must # * contain a list, the Interpret function will know that this is a # * special case, and the event to be solved can be added to the delay_table # * at index id. # * example: # * # * sub do_event { # * my ($ks, $func, $args) = @_; # * my $answers = "[]"; # * # * # a(X) # * if ($func eq "a") { # * # don't know answer yet, wait until later to send response # * $answers = oaa_delay_solution("a_1"); # * } # * return $answers; # * } # ****************************************************************************/ # **************************************************************************** # * name: oaa_return_delayed_solutions # * purpose: Sends the solutions to a delayed event to the Facilitator, # * and removes the event from the delay table. # * inputs: # * - char *id: * Index into the delay table, indicating which event is solved # * - char* answer: The solution list for the delayed event # * returns: # * True if successful # * remarks: # * If answer=NULL, a failed event ([]) is sent to the Facilitator. # * example: # * oaa_return_delayed_solutions("a_1", "[a(1), a(2)]"); # * ************************************************************************* # **************************************************************************** # * Prolog parsing predicates # **************************************************************************** # *************************************************************************** # * name: oaa_functor # * purpose: Splits a string containing a prolog-style term into a functor # * and arguments # * see also: oaa_func returns just the functor # * oaa_args returns the arg part of a structure # * example: # * ($func, $args) = oaa_functor("a(1,2,3)"); # func = "a", args = "1,2,3" # *************************************************************************** # *************************************************************************** # * name: oaa_func # * purpose: Splits a string containing a prolog-style term into a functor # * and arguments, and returns the functor part # * see also: oaa_functor returns the functor and args # oaa_args returns the arg part of a structure # * example: # * $func = oaa_func("a(1,2,3)"); # func = "a" # *************************************************************************** # *************************************************************************** # * name: oaa_args # * purpose: Splits a string containing a prolog-style term into a functor # * and arguments, and returns the args part # * see also: oaa_functor returns the functor part of a structure # * example: # * $args = oaa_args("a(1,2,3)"); # args = "1,2,3" # *************************************************************************** # **************************************************************************** # * name: oaa_term # * purpose: takes a list of terms (comma separated) and returns the first (car) # * and rest (cdr) of the list. # * inputs: # * - char *terms: a list of prolog terms # * outputs: ($aterm, $restterm) # * - char *aterm: the first term in the list # * - char *restterms: the rest of the terms # * remarks: # * - Terms may be nested arbitrarily deep (eg. a(b(c(d,1)), X). # * - Term can correctly parse expression with embedded arguments using # * Japanese JIS7 format. JIS7 is the Japanese encoding standard chosen # * for use with the OAA. Three reasons for this choice: 1) it's the # * most popular standard on UNIX machines. 2) 7-bit encoding should # * be TCP/IP and modem friendly. 3) it's easy to parse: JIS7 embeds # * Japanese characters in a quotation-like wrapper, using ESC$B for the # * opening marker and ESC(B for the closing. # * - If only one term is read, restterms will be "" # * example: # * # loop over list of "1,2,3" # * while ($list) { # * ($elt, $list) = oaa_term($list) # * print $elt."\n"; # * } # ****************************************************************************/ # **************************************************************************** # * name: oaa_nth_elt # * purpose: Returns the Nth term in a list of terms # * inputs: # * - char *list: a string containing a comma-separated list of terms # * - int n: index into a list (nth term) # * returns: # * - char *elt: the nth term in the list. # * remarks: # * 1-based! # * example: # * $a3 = oaa_nth_elt("1,2,3", 3); # $a3 = "3" # **************************************************************************** # **************************************************************************** # * name: oaa_argument # * purpose: Returns the nth argument in a term # * inputs: # * - char *predicate: a prolog-style term: eg func(a1,a2,...) # * - int n: index into a list (nth term) # * returns: # * - char *argument: the nth argument in the term. eg (a2 if n = 2 # * remarks: # * 1-based! # * example: # * $a3 = oaa_argument("func(1,2,3)", 3); # $a3 = "3" # **************************************************************************** # **************************************************************************** # * name: oaa_is_atom # * purpose: Returns true if the term is an atom # **************************************************************************** # **************************************************************************** # * name: oaa_is_var # * purpose: Returns true if the term is a var # **************************************************************************** # **************************************************************************** # * name: oaa_is_group # * purpose: Returns true if the term is a group # * remarks: Examples of groups are [1,2,3], (1,2,3), or {1,2,3} # **************************************************************************** # **************************************************************************** # * name: oaa_is_list # * purpose: Returns true if the term is a list # * remarks: Lists start and end with "[" and "]" # **************************************************************************** # **************************************************************************** # * name: oaa_is_int # * purpose: Returns true if the term is an int # **************************************************************************** # **************************************************************************** # * name: oaa_param_value # * purpose: Extracts the value from a parameter list # * inputs: # * - aList: a parameter list, in the form "[attr1(Value),attr2(Value2)]" # * - param: parameter to extract (e.g. attr1) # * returns: # * - char **Value: value of parameter or NULL if not found # * remarks: # * - most parameter lists should be in the form [p(Val), p2(Val2)]... # * If p has more than one argument, the list is returned # * If p has no arguments, "true" is returned as the value # * examples: # * $p = oaa_param_value("[parallel, num_solutions(3)]", "num_solutions") # * # $p = "3" # ****************************************************************************/ # **************************************************************************** # * Special string functions # **************************************************************************** # **************************************************************************** # * name: oaa_double_quotes # * purpose: Doubles any "'" in the string, to prepare the string to # * be enclosed by "'". # * returns: The modified string # * see also: oaa_undouble_quotes # **************************************************************************** # **************************************************************************** # * name: oaa_undouble_quotes # * purpose: Converts any "''" in the string to just ' # * returns: The modified string # * see also: oaa_double_quotes # **************************************************************************** # **************************************************************************** # * name: oaa_remove_quotes # * purpose: Removes leading and trailing ' and " marks # * returns: The modified string # **************************************************************************** # **************************************************************************** # * name: oaa_trim # * purpose: Removes whitespace surrounding string # * returns: The modified string # **************************************************************************** # **************************************************************************** # * name: oaa_list_len # * purpose: Returns the length of a comma separated list of terms # * returns: The length # **************************************************************************** # **************************************************************************** # * name: oaa_group_to_terms # * purpose: Converts an incoming prolog group [elt1, elt2, elt3] form) into # * a list of terms, on which we can use list_len, NthElt, etc. # * i.e. a comma-separated list "elt1, elt2, etl3". # * Basically, just removes the brackets... # * Groups are any pair that starts with [ or ( or { # * returns: The list without brackets # **************************************************************************** # **************************************************************************** # * name: oaa_list_to_terms # * purpose: Converts an incoming prolog list [elt1, elt2, elt3] form) into # * a list of terms, on which we can use list_len, NthElt, etc. # * i.e. a comma-separated list "elt1, elt2, etl3". # * Basically, just removes the brackets... # * returns: The list without brackets # **************************************************************************** # **************************************************************************** # * name: oaa_unify # * purpose: Perform true unification and return resulting term # * returns: if the two terms unify, returns unified term with all vars # * instantiated. Otherwise return false. # * remarks: # * All variable bindings are stored in global var %bindings # * example: # * $ans = oaa_unify("a(X,2)", "a(b(1), Y)"); # * #ans = "a(b(1),2)" # * $ans = oaa_unify("a(X,X)", "a(1,2)"); # * #ans = $FALSE; # **************************************************************************** # **************************************************************************** # * Sending, receiving data # **************************************************************************** # **************************************************************************** # * name: oaa_send_data # * purpose: Sends raw data to the server (Facilitator # **************************************************************************** # **************************************************************************** # * name: oaa_post_event # * purpose: Sends an event to the server (Facilitator # **************************************************************************** # **************************************************************************** # * name: oaa_get_event # * purpose: Reads an event from the TCP stream. # * returns: ($KS, $Event) # **************************************************************************** # *************************************************************************** # * name: oaa_solve # * purpose: requests data or actions from distributed agents # * inputs: # * - char *goal: an ICL goal to be solve/performed # * - char *params: control parameters describing how the goal should be # * sent/resolved (see below). # * outputs: # * - Answers: a list containing solutions to the requested goal. # * The answer value "[]" constitutes failure of the goal. # * parameters: # * The params argument is a list which may contain: # * # * cache : cache all solutions locally # * level_limit(N) : highest number of levels to climb for # * solutions. # * address(KS) : ask a specific KS to solve goal # * and_parallel : and-parallel solve of Goal list # * or_parallel : or-parallel solve of Goal list # * test(Test) : only solve goal on blackboards where Test # * succeeds locally. # * broadcast : just disseminate message, do not request # * results. # * asynchronous : solve will not block until solution returns, # * the solutions will be returned asynchronously # * in solved(FromKs,Goal,Params,Solutions) messages # * which should be handled by in do_event() # * solution_limit(N): limits the number of solutions found to # * N. Currently only works for 1... # * time_limit(N) : Waits a maximum of N seconds before # * returning (failure if no solution). # * # * remarks: # * If "broadcast" is sent in the parameter list, Ans may be sent as # * NULL. Otherwise, solve will return anwers in a new space which # * should be deallocated using OAA_FREE() when no longer needed. # * example: # * $ans = oaa_solve("parent(adam,P)", "[]"); # * #ans = "[parent(adam, alice), parent(adam, tom)]" # ****************************************************************************/ # **************************************************************************** # * Global data management # ****************************************************************************/ # **************************************************************************** # * name: oaa_write_bb # * purpose: Add information to global data stored on blackboard server # * example: # * write_bb(name, "Adam Cheyer") adds name("Adam Cheyer") on blackboard # **************************************************************************** # **************************************************************************** # * name: oaa_write_replace_bb # * purpose: Add information to global data stored on blackboard server # * replacing old information with new information # **************************************************************************** # **************************************************************************** # * name: oaa_write_once_bb # * purpose: Add information to global data stored on blackboard server # * at most one times (if exists, doesn't write). # **************************************************************************** # **************************************************************************** # * name: oaa_retract_bb # * purpose: Remove information from global data stored on blackboard server # **************************************************************************** # **************************************************************************** # * name: oaa_replace_bb # * purpose: Changes item value from Old to New # **************************************************************************** # **************************************************************************** # * name: oaa_read_bb # * purpose: Retrieves information from Facilitator's global data store # * returns: list containing retults # **************************************************************************** # **************************************************************************** # * name: oaa_can_solve # * purpose: Asks the Facilitator for a list of agents who can solve a Goal # * returns: list containing agent ids # * example: # * $ans = oaa_can_solve("a(X)"); # * #ans = "[34,10,2]" # **************************************************************************** # **************************************************************************** # * name: oaa_add_trigger # * purpose: Adds a trigger to the appropriate agent. # * inputs: # * - char *Kind: may be 'test', 'data', or 'alarm' # * - char *Type: may be 'when', 'if' (single), 'whenever' (permanent) # * - char *OpMask: on_write, on_replace, on_retract, on_write_replace, # * or a list combining several of these # * - char *Template: template against which to match the trigger # * (e.g. data, or test) # * - char *Action: action to be performed if Condition succeeds # * remarks: # * add_trigger/6 does not require a KS to be specified, because the # * KS will be determined automatically: # * data: always installed on Server # * test: installed on appropriate agent by solvable # * alarm: installed on alarm agent # * For 'event' triggers, use add_trigger_on_ks() # **************************************************************************** # **************************************************************************** # * name: oaa_add_trigger_on_ks # * purpose: Adds a trigger to the specified agent. # * inputs: # * - char *KS: KS on which the trigger should be installed # * - char *Kind: may be 'test', 'data', or 'alarm' # * - char *Type: may be 'when', 'if' (single), 'whenever' (permanent) # * - char *Condition: Test condition # * - char *Action: action to be performed if Condition succeeds # * remarks: # * Cannot install a data trigger because data triggers always go on the # * Server agent which is not a valid KS. # **************************************************************************** # ************************************************************************* # * name: oaa_process_all_events # * purpose: Provides the get_event-interpret loop for a non-XWindows # * application. # * remarks: Loops over all events in queue, executing them. # * If timeout is not set (see set_timeout), get_event() blocks # * forever until a new event arrives, so this is an infinite # * loop # * If timeout is set to some value, if no event arrives in the given # * amount of time, TIMEOUT_EVENT is returned and # * oaa_process_all_events returns. # ************************************************************************* # ************************************************************************* # * name: oaa_loop # * purpose: Provides the get_event-interpret loop for a non-XWindows # * application. # * remarks: If a timeout occurs, user-defined hook idle() is called. # ************************************************************************* # ************************************************************************* # * name: oaa_ready # * purpose: Informs the Facilitator that the agent is ready to # * receive events. # ************************************************************************* # **************************************************************************** # * Interpret: handling incoming events # **************************************************************************** # **************************************************************************** # * name: oaa_interpret # * purpose: Executes standard events for all agents, or calls agent-specific # * do_event procedure. # * inputs: # * - char *KS: KS sending the event to be executed # * - char *event: event to be executed # * returns: # * answers: a list of answers. Should be "[]" for failure, or a list # * containing the event with variables replaced with values. # * example: a query "a(X) could return "[a(1),a(2),a(3)]" # ****************************************************************************