Agent wrapper generation

Revision as of 05:10, 26 April 2007 by Colin-adams (Talk | contribs)

Sometimes the situation arises when you have a routine that you want to use as an agent, but the number of parameters required by the routine is fewer than those that will be passed by the agent call. An example from Eiffel Software's Vision2 library:

class
	EV_POINTER_BUTTON_ACTION_SEQUENCE
 
inherit
	EV_ACTION_SEQUENCE [TUPLE [INTEGER, INTEGER, INTEGER, DOUBLE, DOUBLE, DOUBLE, INTEGER, INTEGER]]
	-- EV_ACTION_SEQUENCE [TUPLE [x, y, button: INTEGER; x_tilt, y_tilt, pressure: DOUBLE; screen_x, screen_y: INTEGER]]

If have have a routine that wants to know when a button is pressed, and which button it was, then it needs the `button' argument, but none of the others. Best practice for this situation at the moment (according to Eric Bezault) is to write a wrapper routine that just passes on the `button' argument.

A similar situation is when you have the correct number of arguments, but they are the wrong way round. This happened to me yesterday, so I had to write a wrapper routine.

It would be much nicer if the compiler were able to generate the necessary wrapper code for you. This artcile explores possible syntaxes for these problems.

Argument rotation

A simple solution for specifying a rotation of 2 arguments (or any permutation that does not drop arguments), is to extend the use of the question mark by suffixing it with a decimal specifying the number of the argument to be passed in that location. For example, to index a list of floating point numbers:

floats_list: DS_ARRAYED_LIST [REAL_64]
  -- Floating point numbers
 
floats_map: DS_HASH_TABLE [INTEGER, REAL_64]
  -- Map of floating-point indices within `floats_array'
 
build_map
  -- Build `floats_map' from `floats_list'.
 require
  floats_list_not_void: floats_list /= Void
 do
  create floats_map.make (floats_list.count)
  floats_list.do_all_with_index (agent {DS_HASH_TABLE} floats_map.put_new (?2, ?1))
 end

Dropping arguments

Various notations are possible. It seems to me to be sensible to say that if any occurence of a question mark suffixed by a decimal occurs, then only those arguments are passed, and the compiler should reason about the type of the agent accordingly. We can add a rule that unsuffixed question marks and suffixed question marks cannot be mixed in the same agent call.

The remaining problems are how to indicate that an agent should receive *no* open arguments at all. As empty parentheses are anathema to Eiffel programmers, and no parentheses already means to pass all arguments open, a suitable notation for no closed arguments and no open arguments might be a single underscore within parentheses. This can then be generalized to the case of one or more closed arguments, and no open arguments, by following all closed arguments with a comma followed by a single underscore.

The compiler now has all the information necessary to check the type of the agent, and to generate a wrapper routine (hopefully, a smart optimizing compiler can eliminate the wrapper altogether).