Step 6a expands 2D and 3D vector operations into combinations of 1D operations and structure accessors. It also expands various other operations. Some of these expansions must follow vector expansion. The substeps are:
Even-quotient-scalar-2D and even-quotient-scalar-3D are expanded component-wise. This must be done before detection of missing inputs, because the computation for individuals components might generate a missing value.
Possibly missing inputs to expressions are detected. To be possibly missing, an input must be a point (not, for example, the first input to unscaled-sheet-ref) and not pure. If any inputs might be missing, the expression is enclosed in a binary-if form, which checks whether any of the relevant inputs are missing and, if so, returns a missing value.
After checks pertaining to the whole expression have been wrapped around the expression, the compiler detaches from the expression any subforms headed by unsafe operators. The expression is wrapped in a binary-if form (inside any guards for the overall expression) which checks whether the output of these forms is missing. The unsafe operators are:
This detaching process is starts with the smallest unsafe constituents. Thus, the binary-if clauses for larger unsafe constituents are nested inside those for smaller constituents. This prevents duplicate testing of the same intermediate value when the input code contains unsafe subforms inside other unsafe subforms.
Forms headed by 2D and 3D vector operators are expanded into 1D operations plus structure accessors. The operations to be expanded are:
When processing a form, the compiler first calls this function recursively on its inputs. The resulting forms may then be complex forms headed by begin. A special function is called, which returns the final form and the list of forms that precede it. This function works even on nested begin forms.
Each input is then examined. If it is headed by make-point, it is deconstructed. Otherwise, a temporary variable is allocated (if our input is not a symbol or constant) and the components extracted. This work is done by utility functions (one for each dimensionality).
The main expansion function for each vector operation then calls the utility function for the appropriate dimension, receives the forms for the individual coordinates and a list of forms to be evaluated before them. These items are then used to compose the final expanded form.
This procedure prevents the compiled code from packing up a multi-dimensional point using make-point and then immediately deconstructing it into its components. This could occur, for example, if the form is a nested sequence of vector operations such as addition.
Notice that vector expansion must follow the code that detects missing inputs to expressions, so that the inputs to complex vector expressions are checked only once.
After the generation of checks for missing inputs in step 5b, the results of the purity analysis have served their purpose. We can now remove the pure-ref markings from variable references. We can also expand verify-non-missing into the obvious unary-if form. These rewriting rules can be ordered before or after vector expansion.
Evenly-divides? and zero? are expanded into the obvious tests using modulo. This must follow vector expansion, which reduces the 2D and 3D versions of these operations into the 1D versions. Similarly, even-quotient is expanded (allocating temporary variables when required) using evenly-divides? and quotient.
Guaranteed-quotient is expanded, to include a check verifying that the division is even.
Ownership, Maintenance and Disclaimers
Last modified