|
Reduct
v4.0.5-1-g4851deb
A functional and immutable language.
|
Reduct uses a IR (Intermediate representation) heavily inspired by the RVSDG (Regionalized Value State Dependence Graph).
A RVSDG representation is made up of nodes, regions and edges. Nodes represent operations (addition, subtraction, branches, functions, etc.), regions represent computations (a sequence of nodes) and edges represent data dependencies between nodes.
Each node can have any number of inputs but will always have exactly one output. Each region can have any number of arguments but will also always have exactly one result.
The output of nodes and the arguments of regions are the origins of edges, while the input or results of a region are the users of edges.
Included is a simple description of how data flows through the RVSDG:
A node can either be simple or structural, a simple node represents a primitive operation such as addition or subtraction. Structural nodes contain regions and represent more complex logic such as function calls, loops or conditionals.
There are multiple types of structural node which defines how it passes data to and from the regions it might contain. Included below is a list of all such types.
A gamma node represents a branch or decision point. The first input to a gamma node is a predicate, which should evaluate to a positive integer representing the index of the region to execute. The remaining inputs are passed as arguments to the corresponding region with that regions outputs mapped to the gamma nodes outputs.
A lambda node represents a function and contains a single region representing a function's body. The inputs are not the arguments to the lambda but instead captured variables. The single output is the function itself, not the result of the function.
REDUCT_OPCODE_CALL or REDUCT_OPCODE_CALL_CONST node.A phi node allows a function to recursively call itself. It contains a single region containing a lambda node, the output of the lambda node should be connected to the result of this region with the arguments of this region connected to the inputs of the lambda node. The phi node itself only takes inputs for captured variables and a outputs the lambda.
Data Structures | |
| struct | reduct_rvsdg_origin_t |
| Origin of a data dependency edge. More... | |
| struct | reduct_rvsdg_user_t |
| User of a data dependency edge. More... | |
| struct | reduct_rvsdg_edge_t |
| Edge structure representing a data dependency. More... | |
| struct | reduct_rvsdg_node_info_t |
| Information about a node type. More... | |
| struct | reduct_rvsdg_node_t |
| struct | reduct_rvsdg_region_t |
Macros | |
| #define | REDUCT_RVSDG_NODE_TYPE_INVALID 0 |
| Invalid node type. | |
| #define | REDUCT_RVSDG_NODE_TYPE_SIMPLE_OPCODE 1 |
| Represents a primitive operation (opcode). | |
| #define | REDUCT_RVSDG_NODE_TYPE_SIMPLE_CONST 2 |
| Represents a constant. | |
| #define | REDUCT_RVSDG_NODE_TYPE_GAMMA 3 |
| Represents a branch or decision point. | |
| #define | REDUCT_RVSDG_NODE_TYPE_LAMBDA 4 |
| Represents a function. | |
| #define | REDUCT_RVSDG_NODE_TYPE_PHI 5 |
| Represents a phi node. | |
| #define | REDUCT_RVSDG_NODE_FLAGS_NONE 0 |
| No flags. | |
| #define | REDUCT_RVSDG_NODE_FLAGS_LAMBDA_VARIADIC (1 << 0) |
| Lambda node is variadic. | |
Typedefs | |
| typedef uint8_t | reduct_rvsdg_node_type_t |
| Node type. | |
| typedef uint8_t | reduct_rvsdg_node_flags_t |
| Node flags. | |
Enumerations | |
| enum | reduct_rvsdg_owner_kind_t { REDUCT_RVSDG_OWNER_NODE , REDUCT_RVSDG_OWNER_REGION } |
| Owner of a data dependency origin or user. More... | |
Functions | |
| REDUCT_API const reduct_rvsdg_node_info_t * | reduct_rvsdg_node_get_info (reduct_rvsdg_node_type_t type) |
| Get information about a node type. | |
| REDUCT_API reduct_rvsdg_edge_t * | reduct_rvsdg_edge_new (struct reduct *reduct) |
| Allocate a new IR edge. | |
| REDUCT_API void | reduct_rvsdg_edge_connect (struct reduct *reduct, reduct_rvsdg_origin_t *origin, reduct_rvsdg_user_t *user) |
| Connects an origin to a user via an edge. | |
| REDUCT_API void | reduct_rvsdg_edge_disconnect (reduct_rvsdg_edge_t *edge) |
| Disconnect an edge from its origin and user. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new (struct reduct *reduct) |
| Allocate a new IR node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_simple_opcode (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_opcode_t opcode) |
| Create a simple opcode node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_simple_constant (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_handle_t constant) |
| Create a simple constant node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_simple_unary (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_opcode_t opcode, struct reduct_rvsdg_origin *input) |
| Create a simple unary opcode node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_simple_binary (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_opcode_t opcode, struct reduct_rvsdg_origin *left, struct reduct_rvsdg_origin *right) |
| Create a simple binary opcode node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_simple_ternary (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_opcode_t opcode, struct reduct_rvsdg_origin *a, struct reduct_rvsdg_origin *b, struct reduct_rvsdg_origin *c) |
| Create a simple ternary opcode node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_lambda (struct reduct *reduct, reduct_rvsdg_region_t *region) |
| Create a lambda node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_phi (struct reduct *reduct, reduct_rvsdg_region_t *region) |
| Create a phi node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_gamma (struct reduct *reduct, reduct_rvsdg_region_t *region, uint8_t regionCount) |
| Create a gamma node. | |
| REDUCT_API struct reduct_rvsdg_user * | reduct_rvsdg_node_get_input (reduct_rvsdg_node_t *node, uint16_t index) |
| Get an input port of a node by index. | |
| REDUCT_API struct reduct_rvsdg_origin * | reduct_rvsdg_node_get_input_origin (reduct_rvsdg_node_t *node, uint16_t index) |
| Get the output of the node connected to an input node of a node by index. | |
| REDUCT_API struct reduct_rvsdg_node * | reduct_rvsdg_node_get_input_node (reduct_rvsdg_node_t *node, uint16_t index) |
| Get the node connected to an input node of a node by index. | |
| REDUCT_API void | reduct_rvsdg_origin_redirect_users (struct reduct_rvsdg_origin *origin, struct reduct_rvsdg_origin *newOrigin) |
| Redirect all users of a origin to a new origin. | |
| REDUCT_API struct reduct_rvsdg_origin * | reduct_rvsdg_region_get_argument (reduct_rvsdg_region_t *region, uint16_t index) |
| Get an argument port of a region by index. | |
| REDUCT_API bool | reduct_rvsdg_region_is_ancestor_or_same (reduct_rvsdg_region_t *region, reduct_rvsdg_region_t *ancestor) |
| Check if a region is an ancestor of another, or if they are the same. | |
| REDUCT_API void | reduct_rvsdg_edge_redirect (reduct_rvsdg_edge_t *edge, reduct_rvsdg_origin_t *newOrigin) |
| Redirect an existing edge from its current origin to a new origin. | |
| REDUCT_API void | reduct_rvsdg_node_phi_wrap_lambda (struct reduct *reduct, reduct_rvsdg_node_t *lambda) |
| Wrap a lambda node in a phi node for recursive calls. | |
| REDUCT_API bool | reduct_rvsdg_node_is_inside_phi (reduct_rvsdg_node_t *node) |
| Check if a nodes grandparent is a phi node. | |
| REDUCT_API reduct_rvsdg_node_t * | reduct_rvsdg_node_new_call (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_rvsdg_origin_t *callable) |
| Create a CALL opcode node and connect a callable as its first input. | |
| REDUCT_API bool | reduct_rvsdg_node_map_input_to_argument (reduct_rvsdg_node_t *node, struct reduct_rvsdg_region *region, uint16_t inputIndex, uint16_t *outArgIndex) |
| Map a node input index to a region argument index. | |
| REDUCT_API bool | reduct_rvsdg_node_map_argument_to_input (reduct_rvsdg_node_t *node, struct reduct_rvsdg_region *region, uint16_t argIndex, uint16_t *outInputIndex) |
| Map a region argument index to an input index of the parent node. | |
| REDUCT_API bool | reduct_rvsdg_node_is_recur_origin (reduct_rvsdg_node_t *node, struct reduct_rvsdg_origin *origin) |
| Check if an origin is a recursion target for a given phi node. | |
| REDUCT_API reduct_rvsdg_region_t * | reduct_rvsdg_region_new (struct reduct *reduct) |
| Allocate a new IR region. | |
| REDUCT_API reduct_rvsdg_user_t * | reduct_rvsdg_user_new (struct reduct *reduct) |
| Allocate a new IR user port. | |
| REDUCT_API reduct_rvsdg_origin_t * | reduct_rvsdg_origin_new (struct reduct *reduct) |
| Allocate a new IR origin port. | |
| REDUCT_API reduct_rvsdg_user_t * | reduct_rvsdg_node_add_input (struct reduct *reduct, reduct_rvsdg_node_t *node) |
| Add a new input port to a node. | |
| REDUCT_API reduct_rvsdg_region_t * | reduct_rvsdg_node_add_region (struct reduct *reduct, reduct_rvsdg_node_t *node) |
| Add a new region to a node. | |
| REDUCT_API reduct_rvsdg_origin_t * | reduct_rvsdg_region_add_argument (struct reduct *reduct, reduct_rvsdg_region_t *region) |
| Add a new argument port to a region. | |
| REDUCT_API void | reduct_rvsdg_region_add_node (reduct_rvsdg_region_t *region, reduct_rvsdg_node_t *node) |
| Adds a node to a region. | |
| REDUCT_API void | reduct_rvsdg_region_remove_node (reduct_rvsdg_node_t *node) |
| Removes a node from its region. | |
| REDUCT_API void | reduct_rvsdg_node_delete (struct reduct *reduct, reduct_rvsdg_node_t *node) |
| Removes from the region and disconnects from any connections a node and any nodes connected to its input. | |
| REDUCT_API bool | reduct_rvsdg_node_is_identical (struct reduct *reduct, reduct_rvsdg_node_t *nodeA, reduct_rvsdg_node_t *nodeB) |
| Check if two nodes are structurally identical. | |
| REDUCT_API reduct_rvsdg_origin_t * | reduct_rvsdg_region_lift_origin (struct reduct *reduct, reduct_rvsdg_region_t *region, reduct_rvsdg_origin_t *outerValue) |
| Lift an origin from an outer region to an inner region, creating a new argument in the inner region and connecting it to the outer origin. | |
| REDUCT_API struct reduct_rvsdg_node * | reduct_rvsdg_node_copy (struct reduct *reduct, reduct_rvsdg_region_t *region, struct reduct_rvsdg_node *node) |
| Recursively copy a node. | |
| #define REDUCT_RVSDG_NODE_TYPE_SIMPLE_OPCODE 1 |
| #define REDUCT_RVSDG_NODE_TYPE_SIMPLE_CONST 2 |
| #define REDUCT_RVSDG_NODE_TYPE_GAMMA 3 |
| #define REDUCT_RVSDG_NODE_TYPE_LAMBDA 4 |
| #define REDUCT_RVSDG_NODE_FLAGS_LAMBDA_VARIADIC (1 << 0) |
| typedef uint8_t reduct_rvsdg_node_type_t |
| typedef uint8_t reduct_rvsdg_node_flags_t |
| REDUCT_API const reduct_rvsdg_node_info_t * reduct_rvsdg_node_get_info | ( | reduct_rvsdg_node_type_t | type | ) |
Get information about a node type.
| type | The node type. |
| REDUCT_API reduct_rvsdg_edge_t * reduct_rvsdg_edge_new | ( | struct reduct * | reduct | ) |
Allocate a new IR edge.
| reduct | Pointer to the Reduct structure. |
| REDUCT_API void reduct_rvsdg_edge_connect | ( | struct reduct * | reduct, |
| reduct_rvsdg_origin_t * | origin, | ||
| reduct_rvsdg_user_t * | user | ||
| ) |
Connects an origin to a user via an edge.
| reduct | Pointer to the Reduct structure. |
| origin | Pointer to the origin port. |
| user | Pointer to the user port. |
| REDUCT_API void reduct_rvsdg_edge_disconnect | ( | reduct_rvsdg_edge_t * | edge | ) |
Disconnect an edge from its origin and user.
| edge | Pointer to the edge to disconnect. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new | ( | struct reduct * | reduct | ) |
Allocate a new IR node.
| reduct | Pointer to the Reduct structure. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_simple_opcode | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_opcode_t | opcode | ||
| ) |
Create a simple opcode node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| opcode | The opcode to use. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_simple_constant | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_handle_t | constant | ||
| ) |
Create a simple constant node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| constant | The constant to use. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_simple_unary | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_opcode_t | opcode, | ||
| struct reduct_rvsdg_origin * | input | ||
| ) |
Create a simple unary opcode node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| opcode | The opcode to use. |
| input | The origin of the input. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_simple_binary | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_opcode_t | opcode, | ||
| struct reduct_rvsdg_origin * | left, | ||
| struct reduct_rvsdg_origin * | right | ||
| ) |
Create a simple binary opcode node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| opcode | The opcode to use. |
| left | The origin of the left input. |
| right | The origin of the right input. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_simple_ternary | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_opcode_t | opcode, | ||
| struct reduct_rvsdg_origin * | a, | ||
| struct reduct_rvsdg_origin * | b, | ||
| struct reduct_rvsdg_origin * | c | ||
| ) |
Create a simple ternary opcode node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| opcode | The opcode to use. |
| a | The origin of the first input. |
| b | The origin of the second input. |
| c | The origin of the third input. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_lambda | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region | ||
| ) |
Create a lambda node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_phi | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region | ||
| ) |
Create a phi node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_gamma | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| uint8_t | regionCount | ||
| ) |
Create a gamma node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the node to, or NULL. |
| regionCount | The number of regions (branches) to create. |
| REDUCT_API struct reduct_rvsdg_user * reduct_rvsdg_node_get_input | ( | reduct_rvsdg_node_t * | node, |
| uint16_t | index | ||
| ) |
Get an input port of a node by index.
| node | The node to search. |
| index | The index of the input port. |
| REDUCT_API struct reduct_rvsdg_origin * reduct_rvsdg_node_get_input_origin | ( | reduct_rvsdg_node_t * | node, |
| uint16_t | index | ||
| ) |
Get the output of the node connected to an input node of a node by index.
| node | The node to search. |
| index | The index of the input port. |
| REDUCT_API struct reduct_rvsdg_node * reduct_rvsdg_node_get_input_node | ( | reduct_rvsdg_node_t * | node, |
| uint16_t | index | ||
| ) |
Get the node connected to an input node of a node by index.
| node | The node to search. |
| index | The index of the input port. |
| REDUCT_API void reduct_rvsdg_origin_redirect_users | ( | struct reduct_rvsdg_origin * | origin, |
| struct reduct_rvsdg_origin * | newOrigin | ||
| ) |
Redirect all users of a origin to a new origin.
| origin | The current origin. |
| newOrigin | The new origin to redirect users to. |
| REDUCT_API struct reduct_rvsdg_origin * reduct_rvsdg_region_get_argument | ( | reduct_rvsdg_region_t * | region, |
| uint16_t | index | ||
| ) |
Get an argument port of a region by index.
| region | The region to search. |
| index | The index of the argument port. |
| REDUCT_API bool reduct_rvsdg_region_is_ancestor_or_same | ( | reduct_rvsdg_region_t * | region, |
| reduct_rvsdg_region_t * | ancestor | ||
| ) |
Check if a region is an ancestor of another, or if they are the same.
| region | The region to start from. |
| ancestor | The potential ancestor region. |
ancestor is an ancestor of (or the same as) region. | REDUCT_API void reduct_rvsdg_edge_redirect | ( | reduct_rvsdg_edge_t * | edge, |
| reduct_rvsdg_origin_t * | newOrigin | ||
| ) |
Redirect an existing edge from its current origin to a new origin.
| edge | The edge to redirect. |
| newOrigin | The new origin to connect the edge to. |
| REDUCT_API void reduct_rvsdg_node_phi_wrap_lambda | ( | struct reduct * | reduct, |
| reduct_rvsdg_node_t * | lambda | ||
| ) |
Wrap a lambda node in a phi node for recursive calls.
| reduct | Pointer to the Reduct structure. |
| lambda | The lambda node to wrap. |
| REDUCT_API bool reduct_rvsdg_node_is_inside_phi | ( | reduct_rvsdg_node_t * | node | ) |
Check if a nodes grandparent is a phi node.
| node | The node to check. |
| REDUCT_API reduct_rvsdg_node_t * reduct_rvsdg_node_new_call | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_rvsdg_origin_t * | callable | ||
| ) |
Create a CALL opcode node and connect a callable as its first input.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the call node to. |
| callable | The origin representing the function to call. |
| REDUCT_API bool reduct_rvsdg_node_map_input_to_argument | ( | reduct_rvsdg_node_t * | node, |
| struct reduct_rvsdg_region * | region, | ||
| uint16_t | inputIndex, | ||
| uint16_t * | outArgIndex | ||
| ) |
Map a node input index to a region argument index.
| node | The parent node. |
| region | The target region. |
| inputIndex | The input index on the node. |
| outArgIndex | Pointer to store the mapped argument index. |
| REDUCT_API bool reduct_rvsdg_node_map_argument_to_input | ( | reduct_rvsdg_node_t * | node, |
| struct reduct_rvsdg_region * | region, | ||
| uint16_t | argIndex, | ||
| uint16_t * | outInputIndex | ||
| ) |
Map a region argument index to an input index of the parent node.
| node | The parent node. |
| region | The region containing the argument. |
| argIndex | The argument index within the region. |
| outInputIndex | Pointer to store the mapped input index. |
| REDUCT_API bool reduct_rvsdg_node_is_recur_origin | ( | reduct_rvsdg_node_t * | node, |
| struct reduct_rvsdg_origin * | origin | ||
| ) |
Check if an origin is a recursion target for a given phi node.
| node | The phi node. |
| origin | The origin to check. |
| REDUCT_API reduct_rvsdg_region_t * reduct_rvsdg_region_new | ( | struct reduct * | reduct | ) |
Allocate a new IR region.
| reduct | Pointer to the Reduct structure. |
| REDUCT_API reduct_rvsdg_user_t * reduct_rvsdg_user_new | ( | struct reduct * | reduct | ) |
Allocate a new IR user port.
| reduct | Pointer to the Reduct structure. |
| REDUCT_API reduct_rvsdg_origin_t * reduct_rvsdg_origin_new | ( | struct reduct * | reduct | ) |
Allocate a new IR origin port.
| reduct | Pointer to the Reduct structure. |
| REDUCT_API reduct_rvsdg_user_t * reduct_rvsdg_node_add_input | ( | struct reduct * | reduct, |
| reduct_rvsdg_node_t * | node | ||
| ) |
Add a new input port to a node.
| reduct | Pointer to the Reduct structure. |
| node | The node to add the input to. |
| REDUCT_API reduct_rvsdg_region_t * reduct_rvsdg_node_add_region | ( | struct reduct * | reduct, |
| reduct_rvsdg_node_t * | node | ||
| ) |
Add a new region to a node.
| reduct | Pointer to the Reduct structure. |
| node | The node to add the region to. |
| REDUCT_API reduct_rvsdg_origin_t * reduct_rvsdg_region_add_argument | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region | ||
| ) |
Add a new argument port to a region.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the argument to. |
| REDUCT_API void reduct_rvsdg_region_add_node | ( | reduct_rvsdg_region_t * | region, |
| reduct_rvsdg_node_t * | node | ||
| ) |
Adds a node to a region.
| region | Pointer to the region to add the node to. |
| node | Pointer to the node to add. |
| REDUCT_API void reduct_rvsdg_region_remove_node | ( | reduct_rvsdg_node_t * | node | ) |
Removes a node from its region.
| node | Pointer to the node to remove. |
| REDUCT_API void reduct_rvsdg_node_delete | ( | struct reduct * | reduct, |
| reduct_rvsdg_node_t * | node | ||
| ) |
Removes from the region and disconnects from any connections a node and any nodes connected to its input.
| reduct | Pointer to the Reduct structure. |
| node | Pointer to the node to delete. |
| REDUCT_API bool reduct_rvsdg_node_is_identical | ( | struct reduct * | reduct, |
| reduct_rvsdg_node_t * | nodeA, | ||
| reduct_rvsdg_node_t * | nodeB | ||
| ) |
Check if two nodes are structurally identical.
| reduct | Pointer to the Reduct structure. |
| nodeA | First node. |
| nodeB | Second node. |
| REDUCT_API reduct_rvsdg_origin_t * reduct_rvsdg_region_lift_origin | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| reduct_rvsdg_origin_t * | outerValue | ||
| ) |
Lift an origin from an outer region to an inner region, creating a new argument in the inner region and connecting it to the outer origin.
| reduct | Pointer to the Reduct structure. |
| region | The inner region to lift the origin into. |
| outerValue | The origin in the outer region to lift. |
| REDUCT_API struct reduct_rvsdg_node * reduct_rvsdg_node_copy | ( | struct reduct * | reduct, |
| reduct_rvsdg_region_t * | region, | ||
| struct reduct_rvsdg_node * | node | ||
| ) |
Recursively copy a node.
| reduct | Pointer to the Reduct structure. |
| region | The region to add the copy to, or NULL. |
| node | The node to copy. |