We should work on improving the documentation on this, to make it clearer.
The basic idea is [ FunctionExpr : InputMetaVar AdditionalInputExpr … -> OutputMetaVar ExtraOutputVar …]
Where:
FunctionExpr is an expression that evaluates to a procedure that expects the specified number inputs and produces the specified number of outputs. When the FunctionExpr is a transform name, it is specially handled, so that the input meta var type and additional input exprs can be inferred, if possible. When the optional FunctionExpr is eliminated, the nanopass framework will search through the user supplied transformers looking for one that matches the input and output specifications, and if one does not exist it will auto-generate a transformer that takes a single input of the expected input type, and produces a single output of the expected output type, if such a transformer is applicable with the remaining specification.
InputMetaVar is a meta-var that can represent either a general match (for instance if we have ‘e’ as the meta-var for Expr, and we expect an Expr, we can specify e as the meta-var), or a specific sub-match (for instance if x is the meta-var for Var and x is an Expr, we can specify x and it will ONLY match when the input is a Var, it is effectively shorthand for matching e and asking (Var? e) in the guard). It is also bound for reference in the guard, because the order of evaluation is: match, assuming match, evaluate guard, assuming guard expression is true, evaluate cata-morphims, evaluate body. The InputMetaVar is only treated specially when the pass has an input language. If the pass has an input language, but the transformer or function to be called does not operate over the input language, a * can be specified.
AdditionalInputExpr is any additional input expressions to pass to the function or transformer. Commonly, these are constant expressions, references to input variables, or references to InputMetaVar variables listed to the left of the expression (yes, I know the left-to-right evaluation isn’t very Schemely, though it is more Rackety, and it is just plain useful sometimes), however, it can be any expression, though it will be evaluated each time the cata-morphism is called. The InputMetaVar and AdditionalInputExprs are also optional, and when they are not specified, no variable is bound for the use by the guard, but the most general match is used for the InputMetaVar, and the AdditionalInputExpr are inferred by first looking for input variables from the calling transformer that have the same name as the called transformer, and, when not all of these are available, the default value from the callee is used, if there is one.
OutputMetaVar indicates the expected output type of the transformer to be called. In general, this is expected to be the most general match in the output language, but it doesn’t have to be, especially in the case where we’ve limited the input, we may also have a limited output. If the pass has no output language the OutputMetaVar is not treated specially. If the pass has an output language, but the transformer being called does not have an output language form, this can be specified by using * as the output meta var.
ExtraOutputVar are the variables specified to hold any additional return values (or if the transformer doesn’t return a language form, just the regular return values).
The OutputMetaVar and ExtraOutputVar may also shadow the InputMetaVar.
So, I don’t know if that is more confusing or less confusing, but that is the full explanation :)
-andy:)