/* :markup: markdown */

/*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not  */
/* be modified manually. See                                                  */
/* templates/include/prism/ast.h.erb                                          */
/* if you are looking to modify the                                           */
/* template                                                                   */
/*----------------------------------------------------------------------------*/

/**
 * @file ast.h
 *
 * The abstract syntax tree.
 *
 * --
 */
#ifndef PRISM_AST_H
#define PRISM_AST_H

#include "prism/defines.h"
#include "prism/util/pm_constant_pool.h"
#include "prism/util/pm_integer.h"
#include "prism/util/pm_string.h"

#include <assert.h>
#include <stddef.h>
#include <stdint.h>

/**
 * This enum represents every type of token in the Ruby source.
 */
typedef enum pm_token_type {
    /** final token in the file */
    PM_TOKEN_EOF = 1,

    /** } */
    PM_TOKEN_BRACE_RIGHT,

    /** , */
    PM_TOKEN_COMMA,

    /** } */
    PM_TOKEN_EMBEXPR_END,

    /** do */
    PM_TOKEN_KEYWORD_DO,

    /** else */
    PM_TOKEN_KEYWORD_ELSE,

    /** elsif */
    PM_TOKEN_KEYWORD_ELSIF,

    /** end */
    PM_TOKEN_KEYWORD_END,

    /** ensure */
    PM_TOKEN_KEYWORD_ENSURE,

    /** in */
    PM_TOKEN_KEYWORD_IN,

    /** rescue */
    PM_TOKEN_KEYWORD_RESCUE,

    /** then */
    PM_TOKEN_KEYWORD_THEN,

    /** when */
    PM_TOKEN_KEYWORD_WHEN,

    /** a newline character outside of other tokens */
    PM_TOKEN_NEWLINE,

    /** ) */
    PM_TOKEN_PARENTHESIS_RIGHT,

    /** | */
    PM_TOKEN_PIPE,

    /** ; */
    PM_TOKEN_SEMICOLON,

    /** & */
    PM_TOKEN_AMPERSAND,

    /** && */
    PM_TOKEN_AMPERSAND_AMPERSAND,

    /** &&= */
    PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL,

    /** &. */
    PM_TOKEN_AMPERSAND_DOT,

    /** &= */
    PM_TOKEN_AMPERSAND_EQUAL,

    /** ` */
    PM_TOKEN_BACKTICK,

    /** a back reference */
    PM_TOKEN_BACK_REFERENCE,

    /** ! or !@ */
    PM_TOKEN_BANG,

    /** != */
    PM_TOKEN_BANG_EQUAL,

    /** !~ */
    PM_TOKEN_BANG_TILDE,

    /** { */
    PM_TOKEN_BRACE_LEFT,

    /** [ */
    PM_TOKEN_BRACKET_LEFT,

    /** [ for the beginning of an array */
    PM_TOKEN_BRACKET_LEFT_ARRAY,

    /** [] */
    PM_TOKEN_BRACKET_LEFT_RIGHT,

    /** []= */
    PM_TOKEN_BRACKET_LEFT_RIGHT_EQUAL,

    /** ] */
    PM_TOKEN_BRACKET_RIGHT,

    /** ^ */
    PM_TOKEN_CARET,

    /** ^= */
    PM_TOKEN_CARET_EQUAL,

    /** a character literal */
    PM_TOKEN_CHARACTER_LITERAL,

    /** a class variable */
    PM_TOKEN_CLASS_VARIABLE,

    /** : */
    PM_TOKEN_COLON,

    /** :: */
    PM_TOKEN_COLON_COLON,

    /** a comment */
    PM_TOKEN_COMMENT,

    /** a constant */
    PM_TOKEN_CONSTANT,

    /** the . call operator */
    PM_TOKEN_DOT,

    /** the .. range operator */
    PM_TOKEN_DOT_DOT,

    /** the ... range operator or forwarding parameter */
    PM_TOKEN_DOT_DOT_DOT,

    /** =begin */
    PM_TOKEN_EMBDOC_BEGIN,

    /** =end */
    PM_TOKEN_EMBDOC_END,

    /** a line inside of embedded documentation */
    PM_TOKEN_EMBDOC_LINE,

    /** #{ */
    PM_TOKEN_EMBEXPR_BEGIN,

    /** # */
    PM_TOKEN_EMBVAR,

    /** = */
    PM_TOKEN_EQUAL,

    /** == */
    PM_TOKEN_EQUAL_EQUAL,

    /** === */
    PM_TOKEN_EQUAL_EQUAL_EQUAL,

    /** => */
    PM_TOKEN_EQUAL_GREATER,

    /** =~ */
    PM_TOKEN_EQUAL_TILDE,

    /** a floating point number */
    PM_TOKEN_FLOAT,

    /** a floating pointer number with an imaginary suffix */
    PM_TOKEN_FLOAT_IMAGINARY,

    /** a floating pointer number with a rational suffix */
    PM_TOKEN_FLOAT_RATIONAL,

    /** a floating pointer number with a rational and imaginary suffix */
    PM_TOKEN_FLOAT_RATIONAL_IMAGINARY,

    /** a global variable */
    PM_TOKEN_GLOBAL_VARIABLE,

    /** > */
    PM_TOKEN_GREATER,

    /** >= */
    PM_TOKEN_GREATER_EQUAL,

    /** >> */
    PM_TOKEN_GREATER_GREATER,

    /** >>= */
    PM_TOKEN_GREATER_GREATER_EQUAL,

    /** the end of a heredoc */
    PM_TOKEN_HEREDOC_END,

    /** the start of a heredoc */
    PM_TOKEN_HEREDOC_START,

    /** an identifier */
    PM_TOKEN_IDENTIFIER,

    /** an ignored newline */
    PM_TOKEN_IGNORED_NEWLINE,

    /** an instance variable */
    PM_TOKEN_INSTANCE_VARIABLE,

    /** an integer (any base) */
    PM_TOKEN_INTEGER,

    /** an integer with an imaginary suffix */
    PM_TOKEN_INTEGER_IMAGINARY,

    /** an integer with a rational suffix */
    PM_TOKEN_INTEGER_RATIONAL,

    /** an integer with a rational and imaginary suffix */
    PM_TOKEN_INTEGER_RATIONAL_IMAGINARY,

    /** alias */
    PM_TOKEN_KEYWORD_ALIAS,

    /** and */
    PM_TOKEN_KEYWORD_AND,

    /** begin */
    PM_TOKEN_KEYWORD_BEGIN,

    /** BEGIN */
    PM_TOKEN_KEYWORD_BEGIN_UPCASE,

    /** break */
    PM_TOKEN_KEYWORD_BREAK,

    /** case */
    PM_TOKEN_KEYWORD_CASE,

    /** class */
    PM_TOKEN_KEYWORD_CLASS,

    /** def */
    PM_TOKEN_KEYWORD_DEF,

    /** defined? */
    PM_TOKEN_KEYWORD_DEFINED,

    /** do keyword for a predicate in a while, until, or for loop */
    PM_TOKEN_KEYWORD_DO_LOOP,

    /** END */
    PM_TOKEN_KEYWORD_END_UPCASE,

    /** false */
    PM_TOKEN_KEYWORD_FALSE,

    /** for */
    PM_TOKEN_KEYWORD_FOR,

    /** if */
    PM_TOKEN_KEYWORD_IF,

    /** if in the modifier form */
    PM_TOKEN_KEYWORD_IF_MODIFIER,

    /** module */
    PM_TOKEN_KEYWORD_MODULE,

    /** next */
    PM_TOKEN_KEYWORD_NEXT,

    /** nil */
    PM_TOKEN_KEYWORD_NIL,

    /** not */
    PM_TOKEN_KEYWORD_NOT,

    /** or */
    PM_TOKEN_KEYWORD_OR,

    /** redo */
    PM_TOKEN_KEYWORD_REDO,

    /** rescue in the modifier form */
    PM_TOKEN_KEYWORD_RESCUE_MODIFIER,

    /** retry */
    PM_TOKEN_KEYWORD_RETRY,

    /** return */
    PM_TOKEN_KEYWORD_RETURN,

    /** self */
    PM_TOKEN_KEYWORD_SELF,

    /** super */
    PM_TOKEN_KEYWORD_SUPER,

    /** true */
    PM_TOKEN_KEYWORD_TRUE,

    /** undef */
    PM_TOKEN_KEYWORD_UNDEF,

    /** unless */
    PM_TOKEN_KEYWORD_UNLESS,

    /** unless in the modifier form */
    PM_TOKEN_KEYWORD_UNLESS_MODIFIER,

    /** until */
    PM_TOKEN_KEYWORD_UNTIL,

    /** until in the modifier form */
    PM_TOKEN_KEYWORD_UNTIL_MODIFIER,

    /** while */
    PM_TOKEN_KEYWORD_WHILE,

    /** while in the modifier form */
    PM_TOKEN_KEYWORD_WHILE_MODIFIER,

    /** yield */
    PM_TOKEN_KEYWORD_YIELD,

    /** __ENCODING__ */
    PM_TOKEN_KEYWORD___ENCODING__,

    /** __FILE__ */
    PM_TOKEN_KEYWORD___FILE__,

    /** __LINE__ */
    PM_TOKEN_KEYWORD___LINE__,

    /** a label */
    PM_TOKEN_LABEL,

    /** the end of a label */
    PM_TOKEN_LABEL_END,

    /** { */
    PM_TOKEN_LAMBDA_BEGIN,

    /** < */
    PM_TOKEN_LESS,

    /** <= */
    PM_TOKEN_LESS_EQUAL,

    /** <=> */
    PM_TOKEN_LESS_EQUAL_GREATER,

    /** << */
    PM_TOKEN_LESS_LESS,

    /** <<= */
    PM_TOKEN_LESS_LESS_EQUAL,

    /** a method name */
    PM_TOKEN_METHOD_NAME,

    /** - */
    PM_TOKEN_MINUS,

    /** -= */
    PM_TOKEN_MINUS_EQUAL,

    /** -> */
    PM_TOKEN_MINUS_GREATER,

    /** a numbered reference to a capture group in the previous regular expression match */
    PM_TOKEN_NUMBERED_REFERENCE,

    /** ( */
    PM_TOKEN_PARENTHESIS_LEFT,

    /** ( for a parentheses node */
    PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES,

    /** % */
    PM_TOKEN_PERCENT,

    /** %= */
    PM_TOKEN_PERCENT_EQUAL,

    /** %i */
    PM_TOKEN_PERCENT_LOWER_I,

    /** %w */
    PM_TOKEN_PERCENT_LOWER_W,

    /** %x */
    PM_TOKEN_PERCENT_LOWER_X,

    /** %I */
    PM_TOKEN_PERCENT_UPPER_I,

    /** %W */
    PM_TOKEN_PERCENT_UPPER_W,

    /** |= */
    PM_TOKEN_PIPE_EQUAL,

    /** || */
    PM_TOKEN_PIPE_PIPE,

    /** ||= */
    PM_TOKEN_PIPE_PIPE_EQUAL,

    /** + */
    PM_TOKEN_PLUS,

    /** += */
    PM_TOKEN_PLUS_EQUAL,

    /** ? */
    PM_TOKEN_QUESTION_MARK,

    /** the beginning of a regular expression */
    PM_TOKEN_REGEXP_BEGIN,

    /** the end of a regular expression */
    PM_TOKEN_REGEXP_END,

    /** / */
    PM_TOKEN_SLASH,

    /** /= */
    PM_TOKEN_SLASH_EQUAL,

    /** * */
    PM_TOKEN_STAR,

    /** *= */
    PM_TOKEN_STAR_EQUAL,

    /** ** */
    PM_TOKEN_STAR_STAR,

    /** **= */
    PM_TOKEN_STAR_STAR_EQUAL,

    /** the beginning of a string */
    PM_TOKEN_STRING_BEGIN,

    /** the contents of a string */
    PM_TOKEN_STRING_CONTENT,

    /** the end of a string */
    PM_TOKEN_STRING_END,

    /** the beginning of a symbol */
    PM_TOKEN_SYMBOL_BEGIN,

    /** ~ or ~@ */
    PM_TOKEN_TILDE,

    /** unary & */
    PM_TOKEN_UAMPERSAND,

    /** unary :: */
    PM_TOKEN_UCOLON_COLON,

    /** unary .. operator */
    PM_TOKEN_UDOT_DOT,

    /** unary ... operator */
    PM_TOKEN_UDOT_DOT_DOT,

    /** -@ */
    PM_TOKEN_UMINUS,

    /** -@ for a number */
    PM_TOKEN_UMINUS_NUM,

    /** +@ */
    PM_TOKEN_UPLUS,

    /** unary * */
    PM_TOKEN_USTAR,

    /** unary ** */
    PM_TOKEN_USTAR_STAR,

    /** a separator between words in a list */
    PM_TOKEN_WORDS_SEP,

    /** marker for the point in the file at which the parser should stop */
    PM_TOKEN___END__,

    /** a token that was expected but not found */
    PM_TOKEN_MISSING,

    /** a token that was not present but it is okay */
    PM_TOKEN_NOT_PROVIDED,

    /** The maximum token value. */
    PM_TOKEN_MAXIMUM,
} pm_token_type_t;

/**
 * This struct represents a token in the Ruby source. We use it to track both
 * type and location information.
 */
typedef struct {
    /** The type of the token. */
    pm_token_type_t type;

    /** A pointer to the start location of the token in the source. */
    const uint8_t *start;

    /** A pointer to the end location of the token in the source. */
    const uint8_t *end;
} pm_token_t;

/**
 * This represents a range of bytes in the source string to which a node or
 * token corresponds.
 */
typedef struct {
    /** A pointer to the start location of the range in the source. */
    const uint8_t *start;

    /** A pointer to the end location of the range in the source. */
    const uint8_t *end;
} pm_location_t;

struct pm_node;

/**
 * A list of nodes in the source, most often used for lists of children.
 */
typedef struct pm_node_list {
    /** The number of nodes in the list. */
    size_t size;

    /** The capacity of the list that has been allocated. */
    size_t capacity;

    /** The nodes in the list. */
    struct pm_node **nodes;
} pm_node_list_t;

/**
 * This enum represents every type of node in the Ruby syntax tree.
 */
enum pm_node_type {
    /** AliasGlobalVariableNode */
    PM_ALIAS_GLOBAL_VARIABLE_NODE = 1,

    /** AliasMethodNode */
    PM_ALIAS_METHOD_NODE = 2,

    /** AlternationPatternNode */
    PM_ALTERNATION_PATTERN_NODE = 3,

    /** AndNode */
    PM_AND_NODE = 4,

    /** ArgumentsNode */
    PM_ARGUMENTS_NODE = 5,

    /** ArrayNode */
    PM_ARRAY_NODE = 6,

    /** ArrayPatternNode */
    PM_ARRAY_PATTERN_NODE = 7,

    /** AssocNode */
    PM_ASSOC_NODE = 8,

    /** AssocSplatNode */
    PM_ASSOC_SPLAT_NODE = 9,

    /** BackReferenceReadNode */
    PM_BACK_REFERENCE_READ_NODE = 10,

    /** BeginNode */
    PM_BEGIN_NODE = 11,

    /** BlockArgumentNode */
    PM_BLOCK_ARGUMENT_NODE = 12,

    /** BlockLocalVariableNode */
    PM_BLOCK_LOCAL_VARIABLE_NODE = 13,

    /** BlockNode */
    PM_BLOCK_NODE = 14,

    /** BlockParameterNode */
    PM_BLOCK_PARAMETER_NODE = 15,

    /** BlockParametersNode */
    PM_BLOCK_PARAMETERS_NODE = 16,

    /** BreakNode */
    PM_BREAK_NODE = 17,

    /** CallAndWriteNode */
    PM_CALL_AND_WRITE_NODE = 18,

    /** CallNode */
    PM_CALL_NODE = 19,

    /** CallOperatorWriteNode */
    PM_CALL_OPERATOR_WRITE_NODE = 20,

    /** CallOrWriteNode */
    PM_CALL_OR_WRITE_NODE = 21,

    /** CallTargetNode */
    PM_CALL_TARGET_NODE = 22,

    /** CapturePatternNode */
    PM_CAPTURE_PATTERN_NODE = 23,

    /** CaseMatchNode */
    PM_CASE_MATCH_NODE = 24,

    /** CaseNode */
    PM_CASE_NODE = 25,

    /** ClassNode */
    PM_CLASS_NODE = 26,

    /** ClassVariableAndWriteNode */
    PM_CLASS_VARIABLE_AND_WRITE_NODE = 27,

    /** ClassVariableOperatorWriteNode */
    PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE = 28,

    /** ClassVariableOrWriteNode */
    PM_CLASS_VARIABLE_OR_WRITE_NODE = 29,

    /** ClassVariableReadNode */
    PM_CLASS_VARIABLE_READ_NODE = 30,

    /** ClassVariableTargetNode */
    PM_CLASS_VARIABLE_TARGET_NODE = 31,

    /** ClassVariableWriteNode */
    PM_CLASS_VARIABLE_WRITE_NODE = 32,

    /** ConstantAndWriteNode */
    PM_CONSTANT_AND_WRITE_NODE = 33,

    /** ConstantOperatorWriteNode */
    PM_CONSTANT_OPERATOR_WRITE_NODE = 34,

    /** ConstantOrWriteNode */
    PM_CONSTANT_OR_WRITE_NODE = 35,

    /** ConstantPathAndWriteNode */
    PM_CONSTANT_PATH_AND_WRITE_NODE = 36,

    /** ConstantPathNode */
    PM_CONSTANT_PATH_NODE = 37,

    /** ConstantPathOperatorWriteNode */
    PM_CONSTANT_PATH_OPERATOR_WRITE_NODE = 38,

    /** ConstantPathOrWriteNode */
    PM_CONSTANT_PATH_OR_WRITE_NODE = 39,

    /** ConstantPathTargetNode */
    PM_CONSTANT_PATH_TARGET_NODE = 40,

    /** ConstantPathWriteNode */
    PM_CONSTANT_PATH_WRITE_NODE = 41,

    /** ConstantReadNode */
    PM_CONSTANT_READ_NODE = 42,

    /** ConstantTargetNode */
    PM_CONSTANT_TARGET_NODE = 43,

    /** ConstantWriteNode */
    PM_CONSTANT_WRITE_NODE = 44,

    /** DefNode */
    PM_DEF_NODE = 45,

    /** DefinedNode */
    PM_DEFINED_NODE = 46,

    /** ElseNode */
    PM_ELSE_NODE = 47,

    /** EmbeddedStatementsNode */
    PM_EMBEDDED_STATEMENTS_NODE = 48,

    /** EmbeddedVariableNode */
    PM_EMBEDDED_VARIABLE_NODE = 49,

    /** EnsureNode */
    PM_ENSURE_NODE = 50,

    /** FalseNode */
    PM_FALSE_NODE = 51,

    /** FindPatternNode */
    PM_FIND_PATTERN_NODE = 52,

    /** FlipFlopNode */
    PM_FLIP_FLOP_NODE = 53,

    /** FloatNode */
    PM_FLOAT_NODE = 54,

    /** ForNode */
    PM_FOR_NODE = 55,

    /** ForwardingArgumentsNode */
    PM_FORWARDING_ARGUMENTS_NODE = 56,

    /** ForwardingParameterNode */
    PM_FORWARDING_PARAMETER_NODE = 57,

    /** ForwardingSuperNode */
    PM_FORWARDING_SUPER_NODE = 58,

    /** GlobalVariableAndWriteNode */
    PM_GLOBAL_VARIABLE_AND_WRITE_NODE = 59,

    /** GlobalVariableOperatorWriteNode */
    PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE = 60,

    /** GlobalVariableOrWriteNode */
    PM_GLOBAL_VARIABLE_OR_WRITE_NODE = 61,

    /** GlobalVariableReadNode */
    PM_GLOBAL_VARIABLE_READ_NODE = 62,

    /** GlobalVariableTargetNode */
    PM_GLOBAL_VARIABLE_TARGET_NODE = 63,

    /** GlobalVariableWriteNode */
    PM_GLOBAL_VARIABLE_WRITE_NODE = 64,

    /** HashNode */
    PM_HASH_NODE = 65,

    /** HashPatternNode */
    PM_HASH_PATTERN_NODE = 66,

    /** IfNode */
    PM_IF_NODE = 67,

    /** ImaginaryNode */
    PM_IMAGINARY_NODE = 68,

    /** ImplicitNode */
    PM_IMPLICIT_NODE = 69,

    /** ImplicitRestNode */
    PM_IMPLICIT_REST_NODE = 70,

    /** InNode */
    PM_IN_NODE = 71,

    /** IndexAndWriteNode */
    PM_INDEX_AND_WRITE_NODE = 72,

    /** IndexOperatorWriteNode */
    PM_INDEX_OPERATOR_WRITE_NODE = 73,

    /** IndexOrWriteNode */
    PM_INDEX_OR_WRITE_NODE = 74,

    /** IndexTargetNode */
    PM_INDEX_TARGET_NODE = 75,

    /** InstanceVariableAndWriteNode */
    PM_INSTANCE_VARIABLE_AND_WRITE_NODE = 76,

    /** InstanceVariableOperatorWriteNode */
    PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE = 77,

    /** InstanceVariableOrWriteNode */
    PM_INSTANCE_VARIABLE_OR_WRITE_NODE = 78,

    /** InstanceVariableReadNode */
    PM_INSTANCE_VARIABLE_READ_NODE = 79,

    /** InstanceVariableTargetNode */
    PM_INSTANCE_VARIABLE_TARGET_NODE = 80,

    /** InstanceVariableWriteNode */
    PM_INSTANCE_VARIABLE_WRITE_NODE = 81,

    /** IntegerNode */
    PM_INTEGER_NODE = 82,

    /** InterpolatedMatchLastLineNode */
    PM_INTERPOLATED_MATCH_LAST_LINE_NODE = 83,

    /** InterpolatedRegularExpressionNode */
    PM_INTERPOLATED_REGULAR_EXPRESSION_NODE = 84,

    /** InterpolatedStringNode */
    PM_INTERPOLATED_STRING_NODE = 85,

    /** InterpolatedSymbolNode */
    PM_INTERPOLATED_SYMBOL_NODE = 86,

    /** InterpolatedXStringNode */
    PM_INTERPOLATED_X_STRING_NODE = 87,

    /** ItLocalVariableReadNode */
    PM_IT_LOCAL_VARIABLE_READ_NODE = 88,

    /** ItParametersNode */
    PM_IT_PARAMETERS_NODE = 89,

    /** KeywordHashNode */
    PM_KEYWORD_HASH_NODE = 90,

    /** KeywordRestParameterNode */
    PM_KEYWORD_REST_PARAMETER_NODE = 91,

    /** LambdaNode */
    PM_LAMBDA_NODE = 92,

    /** LocalVariableAndWriteNode */
    PM_LOCAL_VARIABLE_AND_WRITE_NODE = 93,

    /** LocalVariableOperatorWriteNode */
    PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE = 94,

    /** LocalVariableOrWriteNode */
    PM_LOCAL_VARIABLE_OR_WRITE_NODE = 95,

    /** LocalVariableReadNode */
    PM_LOCAL_VARIABLE_READ_NODE = 96,

    /** LocalVariableTargetNode */
    PM_LOCAL_VARIABLE_TARGET_NODE = 97,

    /** LocalVariableWriteNode */
    PM_LOCAL_VARIABLE_WRITE_NODE = 98,

    /** MatchLastLineNode */
    PM_MATCH_LAST_LINE_NODE = 99,

    /** MatchPredicateNode */
    PM_MATCH_PREDICATE_NODE = 100,

    /** MatchRequiredNode */
    PM_MATCH_REQUIRED_NODE = 101,

    /** MatchWriteNode */
    PM_MATCH_WRITE_NODE = 102,

    /** MissingNode */
    PM_MISSING_NODE = 103,

    /** ModuleNode */
    PM_MODULE_NODE = 104,

    /** MultiTargetNode */
    PM_MULTI_TARGET_NODE = 105,

    /** MultiWriteNode */
    PM_MULTI_WRITE_NODE = 106,

    /** NextNode */
    PM_NEXT_NODE = 107,

    /** NilNode */
    PM_NIL_NODE = 108,

    /** NoKeywordsParameterNode */
    PM_NO_KEYWORDS_PARAMETER_NODE = 109,

    /** NumberedParametersNode */
    PM_NUMBERED_PARAMETERS_NODE = 110,

    /** NumberedReferenceReadNode */
    PM_NUMBERED_REFERENCE_READ_NODE = 111,

    /** OptionalKeywordParameterNode */
    PM_OPTIONAL_KEYWORD_PARAMETER_NODE = 112,

    /** OptionalParameterNode */
    PM_OPTIONAL_PARAMETER_NODE = 113,

    /** OrNode */
    PM_OR_NODE = 114,

    /** ParametersNode */
    PM_PARAMETERS_NODE = 115,

    /** ParenthesesNode */
    PM_PARENTHESES_NODE = 116,

    /** PinnedExpressionNode */
    PM_PINNED_EXPRESSION_NODE = 117,

    /** PinnedVariableNode */
    PM_PINNED_VARIABLE_NODE = 118,

    /** PostExecutionNode */
    PM_POST_EXECUTION_NODE = 119,

    /** PreExecutionNode */
    PM_PRE_EXECUTION_NODE = 120,

    /** ProgramNode */
    PM_PROGRAM_NODE = 121,

    /** RangeNode */
    PM_RANGE_NODE = 122,

    /** RationalNode */
    PM_RATIONAL_NODE = 123,

    /** RedoNode */
    PM_REDO_NODE = 124,

    /** RegularExpressionNode */
    PM_REGULAR_EXPRESSION_NODE = 125,

    /** RequiredKeywordParameterNode */
    PM_REQUIRED_KEYWORD_PARAMETER_NODE = 126,

    /** RequiredParameterNode */
    PM_REQUIRED_PARAMETER_NODE = 127,

    /** RescueModifierNode */
    PM_RESCUE_MODIFIER_NODE = 128,

    /** RescueNode */
    PM_RESCUE_NODE = 129,

    /** RestParameterNode */
    PM_REST_PARAMETER_NODE = 130,

    /** RetryNode */
    PM_RETRY_NODE = 131,

    /** ReturnNode */
    PM_RETURN_NODE = 132,

    /** SelfNode */
    PM_SELF_NODE = 133,

    /** ShareableConstantNode */
    PM_SHAREABLE_CONSTANT_NODE = 134,

    /** SingletonClassNode */
    PM_SINGLETON_CLASS_NODE = 135,

    /** SourceEncodingNode */
    PM_SOURCE_ENCODING_NODE = 136,

    /** SourceFileNode */
    PM_SOURCE_FILE_NODE = 137,

    /** SourceLineNode */
    PM_SOURCE_LINE_NODE = 138,

    /** SplatNode */
    PM_SPLAT_NODE = 139,

    /** StatementsNode */
    PM_STATEMENTS_NODE = 140,

    /** StringNode */
    PM_STRING_NODE = 141,

    /** SuperNode */
    PM_SUPER_NODE = 142,

    /** SymbolNode */
    PM_SYMBOL_NODE = 143,

    /** TrueNode */
    PM_TRUE_NODE = 144,

    /** UndefNode */
    PM_UNDEF_NODE = 145,

    /** UnlessNode */
    PM_UNLESS_NODE = 146,

    /** UntilNode */
    PM_UNTIL_NODE = 147,

    /** WhenNode */
    PM_WHEN_NODE = 148,

    /** WhileNode */
    PM_WHILE_NODE = 149,

    /** XStringNode */
    PM_X_STRING_NODE = 150,

    /** YieldNode */
    PM_YIELD_NODE = 151,

    /** A special kind of node used for compilation. */
    PM_SCOPE_NODE
};

/**
 * This is the type of node embedded in the node struct. We explicitly control
 * the size of it here to avoid having the variable-width enum.
 */
typedef uint16_t pm_node_type_t;

/**
 * These are the flags embedded in the node struct. We explicitly control the
 * size of it here to avoid having the variable-width enum.
 */
typedef uint16_t pm_node_flags_t;

/**
 * We store the flags enum in every node in the tree. Some flags are common to
 * all nodes (the ones listed below). Others are specific to certain node types.
 */
static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = 0x1;
static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2;

/**
 * This is the base structure that represents a node in the syntax tree. It is
 * embedded into every node type.
 */
typedef struct pm_node {
    /**
     * This represents the type of the node. It somewhat maps to the nodes that
     * existed in the original grammar and ripper, but it's not a 1:1 mapping.
     */
    pm_node_type_t type;

    /**
     * This represents any flags on the node. Some are common to all nodes, and
     * some are specific to the type of node.
     */
    pm_node_flags_t flags;

    /**
     * The unique identifier for this node, which is deterministic based on the
     * source. It is used to identify unique nodes across parses.
     */
    uint32_t node_id;

    /**
     * This is the location of the node in the source. It's a range of bytes
     * containing a start and an end.
     */
    pm_location_t location;
} pm_node_t;

/**
 * Cast the given node to the base pm_node_t type.
 */
#define PM_NODE_UPCAST(node_) ((pm_node_t *) (node_))

/**
 * Cast the type to an enum to allow the compiler to provide exhaustiveness
 * checking.
 */
#define PM_NODE_TYPE(node_) ((enum pm_node_type) (node_)->type)

/**
 * Return true if the type of the given node matches the given type.
 */
#define PM_NODE_TYPE_P(node_, type_) (PM_NODE_TYPE(node_) == (type_))

/**
 * Return the flags associated with the given node.
 */
#define PM_NODE_FLAGS(node_) (PM_NODE_UPCAST(node_)->flags)

/**
 * Return true if the given flag is set on the given node.
 */
#define PM_NODE_FLAG_P(node_, flag_) ((PM_NODE_FLAGS(node_) & (flag_)) != 0)

/**
 * AliasGlobalVariableNode
 *
 * Represents the use of the `alias` keyword to alias a global variable.
 *
 *     alias $foo $bar
 *     ^^^^^^^^^^^^^^^
 *
 * Type: ::PM_ALIAS_GLOBAL_VARIABLE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_alias_global_variable_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * AliasGlobalVariableNode#new_name
     *
     * Represents the new name of the global variable that can be used after aliasing.
     *
     *     alias $foo $bar
     *           ^^^^
     */
    struct pm_node *new_name;

    /**
     * AliasGlobalVariableNode#old_name
     *
     * Represents the old name of the global variable that can be used before aliasing.
     *
     *     alias $foo $bar
     *                ^^^^
     */
    struct pm_node *old_name;

    /**
     * AliasGlobalVariableNode#keyword_loc
     *
     * The location of the `alias` keyword.
     *
     *     alias $foo $bar
     *     ^^^^^
     */
    pm_location_t keyword_loc;
} pm_alias_global_variable_node_t;

/**
 * AliasMethodNode
 *
 * Represents the use of the `alias` keyword to alias a method.
 *
 *     alias foo bar
 *     ^^^^^^^^^^^^^
 *
 * Type: ::PM_ALIAS_METHOD_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_alias_method_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * AliasMethodNode#new_name
     *
     * Represents the new name of the method that will be aliased.
     *
     *     alias foo bar
     *           ^^^
     *
     *     alias :foo :bar
     *           ^^^^
     *
     *     alias :"#{foo}" :"#{bar}"
     *           ^^^^^^^^^
     */
    struct pm_node *new_name;

    /**
     * AliasMethodNode#old_name
     *
     * Represents the old name of the method that will be aliased.
     *
     *     alias foo bar
     *               ^^^
     *
     *     alias :foo :bar
     *                ^^^^
     *
     *     alias :"#{foo}" :"#{bar}"
     *                     ^^^^^^^^^
     */
    struct pm_node *old_name;

    /**
     * AliasMethodNode#keyword_loc
     *
     * Represents the location of the `alias` keyword.
     *
     *     alias foo bar
     *     ^^^^^
     */
    pm_location_t keyword_loc;
} pm_alias_method_node_t;

/**
 * AlternationPatternNode
 *
 * Represents an alternation pattern in pattern matching.
 *
 *     foo => bar | baz
 *            ^^^^^^^^^
 *
 * Type: ::PM_ALTERNATION_PATTERN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_alternation_pattern_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * AlternationPatternNode#left
     *
     * Represents the left side of the expression.
     *
     *     foo => bar | baz
     *            ^^^
     */
    struct pm_node *left;

    /**
     * AlternationPatternNode#right
     *
     * Represents the right side of the expression.
     *
     *     foo => bar | baz
     *                  ^^^
     */
    struct pm_node *right;

    /**
     * AlternationPatternNode#operator_loc
     *
     * Represents the alternation operator location.
     *
     *     foo => bar | baz
     *                ^
     */
    pm_location_t operator_loc;
} pm_alternation_pattern_node_t;

/**
 * AndNode
 *
 * Represents the use of the `&&` operator or the `and` keyword.
 *
 *     left and right
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_AND_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_and_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * AndNode#left
     *
     * Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     left and right
     *     ^^^^
     *
     *     1 && 2
     *     ^
     */
    struct pm_node *left;

    /**
     * AndNode#right
     *
     * Represents the right side of the expression.
     *
     *     left && right
     *             ^^^^^
     *
     *     1 and 2
     *           ^
     */
    struct pm_node *right;

    /**
     * AndNode#operator_loc
     *
     * The location of the `and` keyword or the `&&` operator.
     *
     *     left and right
     *          ^^^
     */
    pm_location_t operator_loc;
} pm_and_node_t;

/**
 * ArgumentsNode
 *
 * Represents a set of arguments to a method or a keyword.
 *
 *     return foo, bar, baz
 *            ^^^^^^^^^^^^^
 *
 * Type: ::PM_ARGUMENTS_NODE

 * Flags (#pm_arguments_node_flags):
 * * ::PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING
 * * ::PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS
 * * ::PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT
 * * ::PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT
 * * ::PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS
 *
 * @extends pm_node_t
 */
typedef struct pm_arguments_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ArgumentsNode#arguments
     *
     * The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo(bar, baz)
     *         ^^^^^^^^
     */
    struct pm_node_list arguments;
} pm_arguments_node_t;

/**
 * ArrayNode
 *
 * Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i.
 *
 *     [1, 2, 3]
 *     ^^^^^^^^^
 *
 * Type: ::PM_ARRAY_NODE

 * Flags (#pm_array_node_flags):
 * * ::PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT
 *
 * @extends pm_node_t
 */
typedef struct pm_array_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ArrayNode#elements
     *
     * Represent the list of zero or more [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression) within the array.
     */
    struct pm_node_list elements;

    /**
     * ArrayNode#opening_loc
     *
     * Represents the optional source location for the opening token.
     *
     *     [1,2,3]                 # "["
     *     %w[foo bar baz]         # "%w["
     *     %I(apple orange banana) # "%I("
     *     foo = 1, 2, 3           # nil
     */
    pm_location_t opening_loc;

    /**
     * ArrayNode#closing_loc
     *
     * Represents the optional source location for the closing token.
     *
     *     [1,2,3]                 # "]"
     *     %w[foo bar baz]         # "]"
     *     %I(apple orange banana) # ")"
     *     foo = 1, 2, 3           # nil
     */
    pm_location_t closing_loc;
} pm_array_node_t;

/**
 * ArrayPatternNode
 *
 * Represents an array pattern in pattern matching.
 *
 *     foo in 1, 2
 *     ^^^^^^^^^^^
 *
 *     foo in [1, 2]
 *     ^^^^^^^^^^^^^
 *
 *     foo in *bar
 *     ^^^^^^^^^^^
 *
 *     foo in Bar[]
 *     ^^^^^^^^^^^^
 *
 *     foo in Bar[1, 2, 3]
 *     ^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_ARRAY_PATTERN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_array_pattern_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ArrayPatternNode#constant
     *
     * Represents the optional constant preceding the Array
     *
     *     foo in Bar[]
     *            ^^^
     *
     *     foo in Bar[1, 2, 3]
     *            ^^^
     *
     *     foo in Bar::Baz[1, 2, 3]
     *            ^^^^^^^^
     */
    struct pm_node *constant;

    /**
     * ArrayPatternNode#requireds
     *
     * Represents the required elements of the array pattern.
     *
     *     foo in [1, 2]
     *             ^  ^
     */
    struct pm_node_list requireds;

    /**
     * ArrayPatternNode#rest
     *
     * Represents the rest element of the array pattern.
     *
     *     foo in *bar
     *            ^^^^
     */
    struct pm_node *rest;

    /**
     * ArrayPatternNode#posts
     *
     * Represents the elements after the rest element of the array pattern.
     *
     *     foo in *bar, baz
     *                  ^^^
     */
    struct pm_node_list posts;

    /**
     * ArrayPatternNode#opening_loc
     *
     * Represents the opening location of the array pattern.
     *
     *     foo in [1, 2]
     *            ^
     */
    pm_location_t opening_loc;

    /**
     * ArrayPatternNode#closing_loc
     *
     * Represents the closing location of the array pattern.
     *
     *     foo in [1, 2]
     *                 ^
     */
    pm_location_t closing_loc;
} pm_array_pattern_node_t;

/**
 * AssocNode
 *
 * Represents a hash key/value pair.
 *
 *     { a => b }
 *       ^^^^^^
 *
 * Type: ::PM_ASSOC_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_assoc_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * AssocNode#key
     *
     * The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     { a: b }
     *       ^
     *
     *     { foo => bar }
     *       ^^^
     *
     *     { def a; end => 1 }
     *       ^^^^^^^^^^
     */
    struct pm_node *key;

    /**
     * AssocNode#value
     *
     * The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     { foo => bar }
     *              ^^^
     *
     *     { x: 1 }
     *          ^
     */
    struct pm_node *value;

    /**
     * AssocNode#operator_loc
     *
     * The location of the `=>` operator, if present.
     *
     *     { foo => bar }
     *           ^^
     */
    pm_location_t operator_loc;
} pm_assoc_node_t;

/**
 * AssocSplatNode
 *
 * Represents a splat in a hash literal.
 *
 *     { **foo }
 *       ^^^^^
 *
 * Type: ::PM_ASSOC_SPLAT_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_assoc_splat_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * AssocSplatNode#value
     *
     * The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used.
     *
     *     { **foo }
     *         ^^^
     */
    struct pm_node *value;

    /**
     * AssocSplatNode#operator_loc
     *
     * The location of the `**` operator.
     *
     *     { **x }
     *       ^^
     */
    pm_location_t operator_loc;
} pm_assoc_splat_node_t;

/**
 * BackReferenceReadNode
 *
 * Represents reading a reference to a field in the previous match.
 *
 *     $'
 *     ^^
 *
 * Type: ::PM_BACK_REFERENCE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_back_reference_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BackReferenceReadNode#name
     *
     * The name of the back-reference variable, including the leading `$`.
     *
     *     $& # name `:$&`
     *
     *     $+ # name `:$+`
     */
    pm_constant_id_t name;
} pm_back_reference_read_node_t;

/**
 * BeginNode
 *
 * Represents a begin statement.
 *
 *     begin
 *       foo
 *     end
 *     ^^^^^
 *
 * Type: ::PM_BEGIN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_begin_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BeginNode#begin_keyword_loc
     *
     * Represents the location of the `begin` keyword.
     *
     *     begin x end
     *     ^^^^^
     */
    pm_location_t begin_keyword_loc;

    /**
     * BeginNode#statements
     *
     * Represents the statements within the begin block.
     *
     *     begin x end
     *           ^
     */
    struct pm_statements_node *statements;

    /**
     * BeginNode#rescue_clause
     *
     * Represents the rescue clause within the begin block.
     *
     *     begin x; rescue y; end
     *              ^^^^^^^^
     */
    struct pm_rescue_node *rescue_clause;

    /**
     * BeginNode#else_clause
     *
     * Represents the else clause within the begin block.
     *
     *     begin x; rescue y; else z; end
     *                        ^^^^^^
     */
    struct pm_else_node *else_clause;

    /**
     * BeginNode#ensure_clause
     *
     * Represents the ensure clause within the begin block.
     *
     *     begin x; ensure y; end
     *              ^^^^^^^^
     */
    struct pm_ensure_node *ensure_clause;

    /**
     * BeginNode#end_keyword_loc
     *
     * Represents the location of the `end` keyword.
     *
     *     begin x end
     *             ^^^
     */
    pm_location_t end_keyword_loc;
} pm_begin_node_t;

/**
 * BlockArgumentNode
 *
 * Represents a block argument using `&`.
 *
 *     bar(&args)
 *     ^^^^^^^^^^
 *
 * Type: ::PM_BLOCK_ARGUMENT_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_block_argument_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BlockArgumentNode#expression
     *
     * The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo(&args)
     *         ^^^^^
     */
    struct pm_node *expression;

    /**
     * BlockArgumentNode#operator_loc
     *
     * Represents the location of the `&` operator.
     *
     *     foo(&args)
     *         ^
     */
    pm_location_t operator_loc;
} pm_block_argument_node_t;

/**
 * BlockLocalVariableNode
 *
 * Represents a block local variable.
 *
 *     a { |; b| }
 *            ^
 *
 * Type: ::PM_BLOCK_LOCAL_VARIABLE_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_block_local_variable_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BlockLocalVariableNode#name
     *
     * The name of the block local variable.
     *
     *     a { |; b| } # name `:b`
     *            ^
     */
    pm_constant_id_t name;
} pm_block_local_variable_node_t;

/**
 * BlockNode
 *
 * Represents a block of ruby code.
 *
 *     [1, 2, 3].each { |i| puts x }
 *                    ^^^^^^^^^^^^^^
 *
 * Type: ::PM_BLOCK_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_block_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BlockNode#locals
     *
     * The local variables declared in the block.
     *
     *     [1, 2, 3].each { |i| puts x } # locals: [:i]
     *                       ^
     */
    pm_constant_id_list_t locals;

    /**
     * BlockNode#parameters
     *
     * The parameters of the block.
     *
     *     [1, 2, 3].each { |i| puts x }
     *                      ^^^
     *     [1, 2, 3].each { puts _1 }
     *                    ^^^^^^^^^^^
     *     [1, 2, 3].each { puts it }
     *                    ^^^^^^^^^^^
     */
    struct pm_node *parameters;

    /**
     * BlockNode#body
     *
     * The body of the block.
     *
     *     [1, 2, 3].each { |i| puts x }
     *                          ^^^^^^
     */
    struct pm_node *body;

    /**
     * BlockNode#opening_loc
     *
     * Represents the location of the opening `{` or `do`.
     *
     *     [1, 2, 3].each { |i| puts x }
     *                    ^
     */
    pm_location_t opening_loc;

    /**
     * BlockNode#closing_loc
     *
     * Represents the location of the closing `}` or `end`.
     *
     *     [1, 2, 3].each { |i| puts x }
     *                                 ^
     */
    pm_location_t closing_loc;
} pm_block_node_t;

/**
 * BlockParameterNode
 *
 * Represents a block parameter of a method, block, or lambda definition.
 *
 *     def a(&b)
 *           ^^
 *     end
 *
 * Type: ::PM_BLOCK_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_block_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BlockParameterNode#name
     *
     * The name of the block parameter.
     *
     *     def a(&b) # name `:b`
     *            ^
     *     end
     */
    pm_constant_id_t name;

    /**
     * BlockParameterNode#name_loc
     *
     * Represents the location of the block parameter name.
     *
     *     def a(&b)
     *            ^
     */
    pm_location_t name_loc;

    /**
     * BlockParameterNode#operator_loc
     *
     * Represents the location of the `&` operator.
     *
     *     def a(&b)
     *           ^
     *     end
     */
    pm_location_t operator_loc;
} pm_block_parameter_node_t;

/**
 * BlockParametersNode
 *
 * Represents a block's parameters declaration.
 *
 *     -> (a, b = 1; local) { }
 *        ^^^^^^^^^^^^^^^^^
 *
 *     foo do |a, b = 1; local|
 *            ^^^^^^^^^^^^^^^^^
 *     end
 *
 * Type: ::PM_BLOCK_PARAMETERS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_block_parameters_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BlockParametersNode#parameters
     *
     * Represents the parameters of the block.
     *
     *     -> (a, b = 1; local) { }
     *         ^^^^^^^^
     *
     *     foo do |a, b = 1; local|
     *             ^^^^^^^^
     *     end
     */
    struct pm_parameters_node *parameters;

    /**
     * BlockParametersNode#locals
     *
     * Represents the local variables of the block.
     *
     *     -> (a, b = 1; local) { }
     *                   ^^^^^
     *
     *     foo do |a, b = 1; local|
     *                       ^^^^^
     *     end
     */
    struct pm_node_list locals;

    /**
     * BlockParametersNode#opening_loc
     *
     * Represents the opening location of the block parameters.
     *
     *     -> (a, b = 1; local) { }
     *        ^
     *
     *     foo do |a, b = 1; local|
     *            ^
     *     end
     */
    pm_location_t opening_loc;

    /**
     * BlockParametersNode#closing_loc
     *
     * Represents the closing location of the block parameters.
     *
     *     -> (a, b = 1; local) { }
     *                        ^
     *
     *     foo do |a, b = 1; local|
     *                            ^
     *     end
     */
    pm_location_t closing_loc;
} pm_block_parameters_node_t;

/**
 * BreakNode
 *
 * Represents the use of the `break` keyword.
 *
 *     break foo
 *     ^^^^^^^^^
 *
 * Type: ::PM_BREAK_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_break_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * BreakNode#arguments
     *
     * The arguments to the break statement, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     break foo
     *           ^^^
     */
    struct pm_arguments_node *arguments;

    /**
     * BreakNode#keyword_loc
     *
     * The location of the `break` keyword.
     *
     *     break foo
     *     ^^^^^
     */
    pm_location_t keyword_loc;
} pm_break_node_t;

/**
 * CallAndWriteNode
 *
 * Represents the use of the `&&=` operator on a call.
 *
 *     foo.bar &&= value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CALL_AND_WRITE_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_call_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CallAndWriteNode#receiver
     *
     * The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo.bar &&= value
     *     ^^^
     */
    struct pm_node *receiver;

    /**
     * CallAndWriteNode#call_operator_loc
     *
     * Represents the location of the call operator.
     *
     *     foo.bar &&= value
     *        ^
     */
    pm_location_t call_operator_loc;

    /**
     * CallAndWriteNode#message_loc
     *
     * Represents the location of the message.
     *
     *     foo.bar &&= value
     *         ^^^
     */
    pm_location_t message_loc;

    /**
     * CallAndWriteNode#read_name
     *
     * Represents the name of the method being called.
     *
     *     foo.bar &&= value # read_name `:bar`
     *         ^^^
     */
    pm_constant_id_t read_name;

    /**
     * CallAndWriteNode#write_name
     *
     * Represents the name of the method being written to.
     *
     *     foo.bar &&= value # write_name `:bar=`
     *         ^^^
     */
    pm_constant_id_t write_name;

    /**
     * CallAndWriteNode#operator_loc
     *
     * Represents the location of the operator.
     *
     *     foo.bar &&= value
     *             ^^^
     */
    pm_location_t operator_loc;

    /**
     * CallAndWriteNode#value
     *
     * Represents the value being assigned.
     *
     *     foo.bar &&= value
     *                 ^^^^^
     */
    struct pm_node *value;
} pm_call_and_write_node_t;

/**
 * CallNode
 *
 * Represents a method call, in all of the various forms that can take.
 *
 *     foo
 *     ^^^
 *
 *     foo()
 *     ^^^^^
 *
 *     +foo
 *     ^^^^
 *
 *     foo + bar
 *     ^^^^^^^^^
 *
 *     foo.bar
 *     ^^^^^^^
 *
 *     foo&.bar
 *     ^^^^^^^^
 *
 * Type: ::PM_CALL_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_call_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CallNode#receiver
     *
     * The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo.bar
     *     ^^^
     *
     *     +foo
     *      ^^^
     *
     *     foo + bar
     *     ^^^
     */
    struct pm_node *receiver;

    /**
     * CallNode#call_operator_loc
     *
     * Represents the location of the call operator.
     *
     *     foo.bar
     *        ^
     *
     *     foo&.bar
     *        ^^
     */
    pm_location_t call_operator_loc;

    /**
     * CallNode#name
     *
     * Represents the name of the method being called.
     *
     *     foo.bar # name `:foo`
     *     ^^^
     */
    pm_constant_id_t name;

    /**
     * CallNode#message_loc
     *
     * Represents the location of the message.
     *
     *     foo.bar
     *         ^^^
     */
    pm_location_t message_loc;

    /**
     * CallNode#opening_loc
     *
     * Represents the location of the left parenthesis.
     *     foo(bar)
     *        ^
     */
    pm_location_t opening_loc;

    /**
     * CallNode#arguments
     *
     * Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo(bar)
     *         ^^^
     */
    struct pm_arguments_node *arguments;

    /**
     * CallNode#closing_loc
     *
     * Represents the location of the right parenthesis.
     *
     *     foo(bar)
     *            ^
     */
    pm_location_t closing_loc;

    /**
     * CallNode#equal_loc
     *
     * Represents the location of the equal sign, in the case that this is an attribute write.
     *
     *     foo.bar = value
     *             ^
     *
     *     foo[bar] = value
     *              ^
     */
    pm_location_t equal_loc;

    /**
     * CallNode#block
     *
     * Represents the block that is being passed to the method.
     *
     *     foo { |a| a }
     *         ^^^^^^^^^
     */
    struct pm_node *block;
} pm_call_node_t;

/**
 * CallOperatorWriteNode
 *
 * Represents the use of an assignment operator on a call.
 *
 *     foo.bar += baz
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_CALL_OPERATOR_WRITE_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_call_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CallOperatorWriteNode#receiver
     *
     * The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo.bar += value
     *     ^^^
     */
    struct pm_node *receiver;

    /**
     * CallOperatorWriteNode#call_operator_loc
     *
     * Represents the location of the call operator.
     *
     *     foo.bar += value
     *        ^
     */
    pm_location_t call_operator_loc;

    /**
     * CallOperatorWriteNode#message_loc
     *
     * Represents the location of the message.
     *
     *     foo.bar += value
     *         ^^^
     */
    pm_location_t message_loc;

    /**
     * CallOperatorWriteNode#read_name
     *
     * Represents the name of the method being called.
     *
     *     foo.bar += value # read_name `:bar`
     *         ^^^
     */
    pm_constant_id_t read_name;

    /**
     * CallOperatorWriteNode#write_name
     *
     * Represents the name of the method being written to.
     *
     *     foo.bar += value # write_name `:bar=`
     *         ^^^
     */
    pm_constant_id_t write_name;

    /**
     * CallOperatorWriteNode#binary_operator
     *
     * Represents the binary operator being used.
     *
     *     foo.bar += value # binary_operator `:+`
     *             ^
     */
    pm_constant_id_t binary_operator;

    /**
     * CallOperatorWriteNode#binary_operator_loc
     *
     * Represents the location of the binary operator.
     *
     *     foo.bar += value
     *             ^^
     */
    pm_location_t binary_operator_loc;

    /**
     * CallOperatorWriteNode#value
     *
     * Represents the value being assigned.
     *
     *     foo.bar += value
     *                ^^^^^
     */
    struct pm_node *value;
} pm_call_operator_write_node_t;

/**
 * CallOrWriteNode
 *
 * Represents the use of the `||=` operator on a call.
 *
 *     foo.bar ||= value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CALL_OR_WRITE_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_call_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CallOrWriteNode#receiver
     *
     * The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo.bar ||= value
     *     ^^^
     */
    struct pm_node *receiver;

    /**
     * CallOrWriteNode#call_operator_loc
     *
     * Represents the location of the call operator.
     *
     *     foo.bar ||= value
     *        ^
     */
    pm_location_t call_operator_loc;

    /**
     * CallOrWriteNode#message_loc
     *
     * Represents the location of the message.
     *
     *     foo.bar ||= value
     *         ^^^
     */
    pm_location_t message_loc;

    /**
     * CallOrWriteNode#read_name
     *
     * Represents the name of the method being called.
     *
     *     foo.bar ||= value # read_name `:bar`
     *         ^^^
     */
    pm_constant_id_t read_name;

    /**
     * CallOrWriteNode#write_name
     *
     * Represents the name of the method being written to.
     *
     *     foo.bar ||= value # write_name `:bar=`
     *         ^^^
     */
    pm_constant_id_t write_name;

    /**
     * CallOrWriteNode#operator_loc
     *
     * Represents the location of the operator.
     *
     *     foo.bar ||= value
     *             ^^^
     */
    pm_location_t operator_loc;

    /**
     * CallOrWriteNode#value
     *
     * Represents the value being assigned.
     *
     *     foo.bar ||= value
     *                 ^^^^^
     */
    struct pm_node *value;
} pm_call_or_write_node_t;

/**
 * CallTargetNode
 *
 * Represents assigning to a method call.
 *
 *     foo.bar, = 1
 *     ^^^^^^^
 *
 *     begin
 *     rescue => foo.bar
 *               ^^^^^^^
 *     end
 *
 *     for foo.bar in baz do end
 *         ^^^^^^^
 *
 * Type: ::PM_CALL_TARGET_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_call_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CallTargetNode#receiver
     *
     * The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo.bar = 1
     *     ^^^
     */
    struct pm_node *receiver;

    /**
     * CallTargetNode#call_operator_loc
     *
     * Represents the location of the call operator.
     *
     *     foo.bar = 1
     *        ^
     */
    pm_location_t call_operator_loc;

    /**
     * CallTargetNode#name
     *
     * Represents the name of the method being called.
     *
     *     foo.bar = 1 # name `:foo`
     *     ^^^
     */
    pm_constant_id_t name;

    /**
     * CallTargetNode#message_loc
     *
     * Represents the location of the message.
     *
     *     foo.bar = 1
     *         ^^^
     */
    pm_location_t message_loc;
} pm_call_target_node_t;

/**
 * CapturePatternNode
 *
 * Represents assigning to a local variable in pattern matching.
 *
 *     foo => [bar => baz]
 *            ^^^^^^^^^^^^
 *
 * Type: ::PM_CAPTURE_PATTERN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_capture_pattern_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CapturePatternNode#value
     *
     * Represents the value to capture.
     *
     *     foo => bar
     *            ^^^
     */
    struct pm_node *value;

    /**
     * CapturePatternNode#target
     *
     * Represents the target of the capture.
     *
     *     foo => bar
     *     ^^^
     */
    struct pm_local_variable_target_node *target;

    /**
     * CapturePatternNode#operator_loc
     *
     * Represents the location of the `=>` operator.
     *
     *     foo => bar
     *         ^^
     */
    pm_location_t operator_loc;
} pm_capture_pattern_node_t;

/**
 * CaseMatchNode
 *
 * Represents the use of a case statement for pattern matching.
 *
 *     case true
 *     in false
 *     end
 *     ^^^^^^^^^
 *
 * Type: ::PM_CASE_MATCH_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_case_match_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CaseMatchNode#predicate
     *
     * Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     case true; in false; end
     *     ^^^^
     */
    struct pm_node *predicate;

    /**
     * CaseMatchNode#conditions
     *
     * Represents the conditions of the case match.
     *
     *     case true; in false; end
     *                ^^^^^^^^
     */
    struct pm_node_list conditions;

    /**
     * CaseMatchNode#else_clause
     *
     * Represents the else clause of the case match.
     *
     *     case true; in false; else; end
     *                          ^^^^
     */
    struct pm_else_node *else_clause;

    /**
     * CaseMatchNode#case_keyword_loc
     *
     * Represents the location of the `case` keyword.
     *
     *     case true; in false; end
     *     ^^^^
     */
    pm_location_t case_keyword_loc;

    /**
     * CaseMatchNode#end_keyword_loc
     *
     * Represents the location of the `end` keyword.
     *
     *     case true; in false; end
     *                          ^^^
     */
    pm_location_t end_keyword_loc;
} pm_case_match_node_t;

/**
 * CaseNode
 *
 * Represents the use of a case statement.
 *
 *     case true
 *     when false
 *     end
 *     ^^^^^^^^^^
 *
 * Type: ::PM_CASE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_case_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * CaseNode#predicate
     *
     * Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     case true; when false; end
     *          ^^^^
     */
    struct pm_node *predicate;

    /**
     * CaseNode#conditions
     *
     * Represents the conditions of the case statement.
     *
     *     case true; when false; end
     *                ^^^^^^^^^^
     */
    struct pm_node_list conditions;

    /**
     * CaseNode#else_clause
     *
     * Represents the else clause of the case statement.
     *
     *     case true; when false; else; end
     *                            ^^^^
     */
    struct pm_else_node *else_clause;

    /**
     * CaseNode#case_keyword_loc
     *
     * Represents the location of the `case` keyword.
     *
     *     case true; when false; end
     *     ^^^^
     */
    pm_location_t case_keyword_loc;

    /**
     * CaseNode#end_keyword_loc
     *
     * Represents the location of the `end` keyword.
     *
     *     case true; when false; end
     *                            ^^^
     */
    pm_location_t end_keyword_loc;
} pm_case_node_t;

/**
 * ClassNode
 *
 * Represents a class declaration involving the `class` keyword.
 *
 *     class Foo end
 *     ^^^^^^^^^^^^^
 *
 * Type: ::PM_CLASS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassNode#locals
     */
    pm_constant_id_list_t locals;

    /**
     * ClassNode#class_keyword_loc
     *
     * Represents the location of the `class` keyword.
     *
     *     class Foo end
     *     ^^^^^
     */
    pm_location_t class_keyword_loc;

    /**
     * ClassNode#constant_path
     */
    struct pm_node *constant_path;

    /**
     * ClassNode#inheritance_operator_loc
     *
     * Represents the location of the `<` operator.
     *
     *     class Foo < Bar
     *               ^
     */
    pm_location_t inheritance_operator_loc;

    /**
     * ClassNode#superclass
     *
     * Represents the superclass of the class.
     *
     *     class Foo < Bar
     *                 ^^^
     */
    struct pm_node *superclass;

    /**
     * ClassNode#body
     *
     * Represents the body of the class.
     *
     *     class Foo
     *       foo
     *       ^^^
     */
    struct pm_node *body;

    /**
     * ClassNode#end_keyword_loc
     *
     * Represents the location of the `end` keyword.
     *
     *     class Foo end
     *               ^^^
     */
    pm_location_t end_keyword_loc;

    /**
     * ClassNode#name
     *
     * The name of the class.
     *
     *     class Foo end # name `:Foo`
     */
    pm_constant_id_t name;
} pm_class_node_t;

/**
 * ClassVariableAndWriteNode
 *
 * Represents the use of the `&&=` operator for assignment to a class variable.
 *
 *     @@target &&= value
 *     ^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CLASS_VARIABLE_AND_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_variable_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassVariableAndWriteNode#name
     *
     * The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     @@target &&= value # name `:@@target`
     *     ^^^^^^^^
     */
    pm_constant_id_t name;

    /**
     * ClassVariableAndWriteNode#name_loc
     *
     * Represents the location of the variable name.
     *
     *     @@target &&= value
     *     ^^^^^^^^
     */
    pm_location_t name_loc;

    /**
     * ClassVariableAndWriteNode#operator_loc
     *
     * Represents the location of the `&&=` operator.
     *
     *     @@target &&= value
     *              ^^^
     */
    pm_location_t operator_loc;

    /**
     * ClassVariableAndWriteNode#value
     *
     * Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     @@target &&= value
     *                  ^^^^^
     */
    struct pm_node *value;
} pm_class_variable_and_write_node_t;

/**
 * ClassVariableOperatorWriteNode
 *
 * Represents assigning to a class variable using an operator that isn't `=`.
 *
 *     @@target += value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_variable_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassVariableOperatorWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * ClassVariableOperatorWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * ClassVariableOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * ClassVariableOperatorWriteNode#value
     */
    struct pm_node *value;

    /**
     * ClassVariableOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;
} pm_class_variable_operator_write_node_t;

/**
 * ClassVariableOrWriteNode
 *
 * Represents the use of the `||=` operator for assignment to a class variable.
 *
 *     @@target ||= value
 *     ^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CLASS_VARIABLE_OR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_variable_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassVariableOrWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * ClassVariableOrWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * ClassVariableOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * ClassVariableOrWriteNode#value
     */
    struct pm_node *value;
} pm_class_variable_or_write_node_t;

/**
 * ClassVariableReadNode
 *
 * Represents referencing a class variable.
 *
 *     @@foo
 *     ^^^^^
 *
 * Type: ::PM_CLASS_VARIABLE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_variable_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassVariableReadNode#name
     *
     * The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     @@abc   # name `:@@abc`
     *
     *     @@_test # name `:@@_test`
     */
    pm_constant_id_t name;
} pm_class_variable_read_node_t;

/**
 * ClassVariableTargetNode
 *
 * Represents writing to a class variable in a context that doesn't have an explicit value.
 *
 *     @@foo, @@bar = baz
 *     ^^^^^  ^^^^^
 *
 * Type: ::PM_CLASS_VARIABLE_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_variable_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassVariableTargetNode#name
     */
    pm_constant_id_t name;
} pm_class_variable_target_node_t;

/**
 * ClassVariableWriteNode
 *
 * Represents writing to a class variable.
 *
 *     @@foo = 1
 *     ^^^^^^^^^
 *
 * Type: ::PM_CLASS_VARIABLE_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_class_variable_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ClassVariableWriteNode#name
     *
     * The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     @@abc = 123     # name `@@abc`
     *
     *     @@_test = :test # name `@@_test`
     */
    pm_constant_id_t name;

    /**
     * ClassVariableWriteNode#name_loc
     *
     * The location of the variable name.
     *
     *     @@foo = :bar
     *     ^^^^^
     */
    pm_location_t name_loc;

    /**
     * ClassVariableWriteNode#value
     *
     * The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     @@foo = :bar
     *             ^^^^
     *
     *     @@_xyz = 123
     *              ^^^
     */
    struct pm_node *value;

    /**
     * ClassVariableWriteNode#operator_loc
     *
     * The location of the `=` operator.
     *
     *     @@foo = :bar
     *           ^
     */
    pm_location_t operator_loc;
} pm_class_variable_write_node_t;

/**
 * ConstantAndWriteNode
 *
 * Represents the use of the `&&=` operator for assignment to a constant.
 *
 *     Target &&= value
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_AND_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantAndWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * ConstantAndWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * ConstantAndWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * ConstantAndWriteNode#value
     */
    struct pm_node *value;
} pm_constant_and_write_node_t;

/**
 * ConstantOperatorWriteNode
 *
 * Represents assigning to a constant using an operator that isn't `=`.
 *
 *     Target += value
 *     ^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_OPERATOR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantOperatorWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * ConstantOperatorWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * ConstantOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * ConstantOperatorWriteNode#value
     */
    struct pm_node *value;

    /**
     * ConstantOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;
} pm_constant_operator_write_node_t;

/**
 * ConstantOrWriteNode
 *
 * Represents the use of the `||=` operator for assignment to a constant.
 *
 *     Target ||= value
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_OR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantOrWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * ConstantOrWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * ConstantOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * ConstantOrWriteNode#value
     */
    struct pm_node *value;
} pm_constant_or_write_node_t;

/**
 * ConstantPathAndWriteNode
 *
 * Represents the use of the `&&=` operator for assignment to a constant path.
 *
 *     Parent::Child &&= value
 *     ^^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_PATH_AND_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_path_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantPathAndWriteNode#target
     */
    struct pm_constant_path_node *target;

    /**
     * ConstantPathAndWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * ConstantPathAndWriteNode#value
     */
    struct pm_node *value;
} pm_constant_path_and_write_node_t;

/**
 * ConstantPathNode
 *
 * Represents accessing a constant through a path of `::` operators.
 *
 *     Foo::Bar
 *     ^^^^^^^^
 *
 * Type: ::PM_CONSTANT_PATH_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_path_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantPathNode#parent
     *
     * The left-hand node of the path, if present. It can be `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It will be `nil` when the constant lookup is at the root of the module tree.
     *
     *     Foo::Bar
     *     ^^^
     *
     *     self::Test
     *     ^^^^
     *
     *     a.b::C
     *     ^^^
     */
    struct pm_node *parent;

    /**
     * ConstantPathNode#name
     *
     * The name of the constant being accessed. This could be `nil` in the event of a syntax error.
     */
    pm_constant_id_t name;

    /**
     * ConstantPathNode#delimiter_loc
     *
     * The location of the `::` delimiter.
     *
     *     ::Foo
     *     ^^
     *
     *     One::Two
     *        ^^
     */
    pm_location_t delimiter_loc;

    /**
     * ConstantPathNode#name_loc
     *
     * The location of the name of the constant.
     *
     *     ::Foo
     *       ^^^
     *
     *     One::Two
     *          ^^^
     */
    pm_location_t name_loc;
} pm_constant_path_node_t;

/**
 * ConstantPathOperatorWriteNode
 *
 * Represents assigning to a constant path using an operator that isn't `=`.
 *
 *     Parent::Child += value
 *     ^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_PATH_OPERATOR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_path_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantPathOperatorWriteNode#target
     */
    struct pm_constant_path_node *target;

    /**
     * ConstantPathOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * ConstantPathOperatorWriteNode#value
     */
    struct pm_node *value;

    /**
     * ConstantPathOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;
} pm_constant_path_operator_write_node_t;

/**
 * ConstantPathOrWriteNode
 *
 * Represents the use of the `||=` operator for assignment to a constant path.
 *
 *     Parent::Child ||= value
 *     ^^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_PATH_OR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_path_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantPathOrWriteNode#target
     */
    struct pm_constant_path_node *target;

    /**
     * ConstantPathOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * ConstantPathOrWriteNode#value
     */
    struct pm_node *value;
} pm_constant_path_or_write_node_t;

/**
 * ConstantPathTargetNode
 *
 * Represents writing to a constant path in a context that doesn't have an explicit value.
 *
 *     Foo::Foo, Bar::Bar = baz
 *     ^^^^^^^^  ^^^^^^^^
 *
 * Type: ::PM_CONSTANT_PATH_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_path_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantPathTargetNode#parent
     */
    struct pm_node *parent;

    /**
     * ConstantPathTargetNode#name
     */
    pm_constant_id_t name;

    /**
     * ConstantPathTargetNode#delimiter_loc
     */
    pm_location_t delimiter_loc;

    /**
     * ConstantPathTargetNode#name_loc
     */
    pm_location_t name_loc;
} pm_constant_path_target_node_t;

/**
 * ConstantPathWriteNode
 *
 * Represents writing to a constant path.
 *
 *     ::Foo = 1
 *     ^^^^^^^^^
 *
 *     Foo::Bar = 1
 *     ^^^^^^^^^^^^
 *
 *     ::Foo::Bar = 1
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_CONSTANT_PATH_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_path_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantPathWriteNode#target
     *
     * A node representing the constant path being written to.
     *
     *     Foo::Bar = 1
     *     ^^^^^^^^
     *
     *     ::Foo = :abc
     *     ^^^^^
     */
    struct pm_constant_path_node *target;

    /**
     * ConstantPathWriteNode#operator_loc
     *
     * The location of the `=` operator.
     *
     *     ::ABC = 123
     *           ^
     */
    pm_location_t operator_loc;

    /**
     * ConstantPathWriteNode#value
     *
     * The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     FOO::BAR = :abc
     *                ^^^^
     */
    struct pm_node *value;
} pm_constant_path_write_node_t;

/**
 * ConstantReadNode
 *
 * Represents referencing a constant.
 *
 *     Foo
 *     ^^^
 *
 * Type: ::PM_CONSTANT_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantReadNode#name
     *
     * The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants).
     *
     *     X              # name `:X`
     *
     *     SOME_CONSTANT  # name `:SOME_CONSTANT`
     */
    pm_constant_id_t name;
} pm_constant_read_node_t;

/**
 * ConstantTargetNode
 *
 * Represents writing to a constant in a context that doesn't have an explicit value.
 *
 *     Foo, Bar = baz
 *     ^^^  ^^^
 *
 * Type: ::PM_CONSTANT_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantTargetNode#name
     */
    pm_constant_id_t name;
} pm_constant_target_node_t;

/**
 * ConstantWriteNode
 *
 * Represents writing to a constant.
 *
 *     Foo = 1
 *     ^^^^^^^
 *
 * Type: ::PM_CONSTANT_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_constant_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ConstantWriteNode#name
     *
     * The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants).
     *
     *     Foo = :bar # name `:Foo`
     *
     *     XYZ = 1    # name `:XYZ`
     */
    pm_constant_id_t name;

    /**
     * ConstantWriteNode#name_loc
     *
     * The location of the constant name.
     *
     *     FOO = 1
     *     ^^^
     */
    pm_location_t name_loc;

    /**
     * ConstantWriteNode#value
     *
     * The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     FOO = :bar
     *           ^^^^
     *
     *     MyClass = Class.new
     *               ^^^^^^^^^
     */
    struct pm_node *value;

    /**
     * ConstantWriteNode#operator_loc
     *
     * The location of the `=` operator.
     *
     *     FOO = :bar
     *         ^
     */
    pm_location_t operator_loc;
} pm_constant_write_node_t;

/**
 * DefNode
 *
 * Represents a method definition.
 *
 *     def method
 *     end
 *     ^^^^^^^^^^
 *
 * Type: ::PM_DEF_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_def_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * DefNode#name
     */
    pm_constant_id_t name;

    /**
     * DefNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * DefNode#receiver
     */
    struct pm_node *receiver;

    /**
     * DefNode#parameters
     */
    struct pm_parameters_node *parameters;

    /**
     * DefNode#body
     */
    struct pm_node *body;

    /**
     * DefNode#locals
     */
    pm_constant_id_list_t locals;

    /**
     * DefNode#def_keyword_loc
     */
    pm_location_t def_keyword_loc;

    /**
     * DefNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * DefNode#lparen_loc
     */
    pm_location_t lparen_loc;

    /**
     * DefNode#rparen_loc
     */
    pm_location_t rparen_loc;

    /**
     * DefNode#equal_loc
     */
    pm_location_t equal_loc;

    /**
     * DefNode#end_keyword_loc
     */
    pm_location_t end_keyword_loc;
} pm_def_node_t;

/**
 * DefinedNode
 *
 * Represents the use of the `defined?` keyword.
 *
 *     defined?(a)
 *     ^^^^^^^^^^^
 *
 * Type: ::PM_DEFINED_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_defined_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * DefinedNode#lparen_loc
     */
    pm_location_t lparen_loc;

    /**
     * DefinedNode#value
     */
    struct pm_node *value;

    /**
     * DefinedNode#rparen_loc
     */
    pm_location_t rparen_loc;

    /**
     * DefinedNode#keyword_loc
     */
    pm_location_t keyword_loc;
} pm_defined_node_t;

/**
 * ElseNode
 *
 * Represents an `else` clause in a `case`, `if`, or `unless` statement.
 *
 *     if a then b else c end
 *                 ^^^^^^^^^^
 *
 * Type: ::PM_ELSE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_else_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ElseNode#else_keyword_loc
     */
    pm_location_t else_keyword_loc;

    /**
     * ElseNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * ElseNode#end_keyword_loc
     */
    pm_location_t end_keyword_loc;
} pm_else_node_t;

/**
 * EmbeddedStatementsNode
 *
 * Represents an interpolated set of statements.
 *
 *     "foo #{bar}"
 *          ^^^^^^
 *
 * Type: ::PM_EMBEDDED_STATEMENTS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_embedded_statements_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * EmbeddedStatementsNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * EmbeddedStatementsNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * EmbeddedStatementsNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_embedded_statements_node_t;

/**
 * EmbeddedVariableNode
 *
 * Represents an interpolated variable.
 *
 *     "foo #@bar"
 *          ^^^^^
 *
 * Type: ::PM_EMBEDDED_VARIABLE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_embedded_variable_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * EmbeddedVariableNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * EmbeddedVariableNode#variable
     */
    struct pm_node *variable;
} pm_embedded_variable_node_t;

/**
 * EnsureNode
 *
 * Represents an `ensure` clause in a `begin` statement.
 *
 *     begin
 *       foo
 *     ensure
 *     ^^^^^^
 *       bar
 *     end
 *
 * Type: ::PM_ENSURE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_ensure_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * EnsureNode#ensure_keyword_loc
     */
    pm_location_t ensure_keyword_loc;

    /**
     * EnsureNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * EnsureNode#end_keyword_loc
     */
    pm_location_t end_keyword_loc;
} pm_ensure_node_t;

/**
 * FalseNode
 *
 * Represents the use of the literal `false` keyword.
 *
 *     false
 *     ^^^^^
 *
 * Type: ::PM_FALSE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_false_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_false_node_t;

/**
 * FindPatternNode
 *
 * Represents a find pattern in pattern matching.
 *
 *     foo in *bar, baz, *qux
 *            ^^^^^^^^^^^^^^^
 *
 *     foo in [*bar, baz, *qux]
 *            ^^^^^^^^^^^^^^^^^
 *
 *     foo in Foo(*bar, baz, *qux)
 *            ^^^^^^^^^^^^^^^^^^^^
 *
 *     foo => *bar, baz, *qux
 *            ^^^^^^^^^^^^^^^
 *
 * Type: ::PM_FIND_PATTERN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_find_pattern_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * FindPatternNode#constant
     *
     * Represents the optional constant preceding the pattern
     *
     *     foo in Foo(*bar, baz, *qux)
     *            ^^^
     */
    struct pm_node *constant;

    /**
     * FindPatternNode#left
     *
     * Represents the first wildcard node in the pattern.
     *
     *     foo in *bar, baz, *qux
     *            ^^^^
     *
     *     foo in Foo(*bar, baz, *qux)
     *                ^^^^
     */
    struct pm_splat_node *left;

    /**
     * FindPatternNode#requireds
     *
     * Represents the nodes in between the wildcards.
     *
     *     foo in *bar, baz, *qux
     *                  ^^^
     *
     *     foo in Foo(*bar, baz, 1, *qux)
     *                      ^^^^^^
     */
    struct pm_node_list requireds;

    /**
     * FindPatternNode#right
     *
     * Represents the second wildcard node in the pattern.
     *
     *     foo in *bar, baz, *qux
     *                       ^^^^
     *
     *     foo in Foo(*bar, baz, *qux)
     *                           ^^^^
     */
    struct pm_node *right;

    /**
     * FindPatternNode#opening_loc
     *
     * The location of the opening brace.
     *
     *     foo in [*bar, baz, *qux]
     *            ^
     *
     *     foo in Foo(*bar, baz, *qux)
     *               ^
     */
    pm_location_t opening_loc;

    /**
     * FindPatternNode#closing_loc
     *
     * The location of the closing brace.
     *
     *     foo in [*bar, baz, *qux]
     *                            ^
     *
     *     foo in Foo(*bar, baz, *qux)
     *                               ^
     */
    pm_location_t closing_loc;
} pm_find_pattern_node_t;

/**
 * FlipFlopNode
 *
 * Represents the use of the `..` or `...` operators to create flip flops.
 *
 *     baz if foo .. bar
 *            ^^^^^^^^^^
 *
 * Type: ::PM_FLIP_FLOP_NODE

 * Flags (#pm_range_flags):
 * * ::PM_RANGE_FLAGS_EXCLUDE_END
 *
 * @extends pm_node_t
 */
typedef struct pm_flip_flop_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * FlipFlopNode#left
     */
    struct pm_node *left;

    /**
     * FlipFlopNode#right
     */
    struct pm_node *right;

    /**
     * FlipFlopNode#operator_loc
     */
    pm_location_t operator_loc;
} pm_flip_flop_node_t;

/**
 * FloatNode
 *
 * Represents a floating point number literal.
 *
 *     1.0
 *     ^^^
 *
 * Type: ::PM_FLOAT_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_float_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * FloatNode#value
     *
     * The value of the floating point number as a Float.
     */
    double value;
} pm_float_node_t;

/**
 * ForNode
 *
 * Represents the use of the `for` keyword.
 *
 *     for i in a end
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_FOR_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_for_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ForNode#index
     *
     * The index expression for `for` loops.
     *
     *     for i in a end
     *         ^
     */
    struct pm_node *index;

    /**
     * ForNode#collection
     *
     * The collection to iterate over.
     *
     *     for i in a end
     *              ^
     */
    struct pm_node *collection;

    /**
     * ForNode#statements
     *
     * Represents the body of statements to execute for each iteration of the loop.
     *
     *     for i in a
     *       foo(i)
     *       ^^^^^^
     *     end
     */
    struct pm_statements_node *statements;

    /**
     * ForNode#for_keyword_loc
     *
     * The location of the `for` keyword.
     *
     *     for i in a end
     *     ^^^
     */
    pm_location_t for_keyword_loc;

    /**
     * ForNode#in_keyword_loc
     *
     * The location of the `in` keyword.
     *
     *     for i in a end
     *           ^^
     */
    pm_location_t in_keyword_loc;

    /**
     * ForNode#do_keyword_loc
     *
     * The location of the `do` keyword, if present.
     *
     *     for i in a do end
     *                ^^
     */
    pm_location_t do_keyword_loc;

    /**
     * ForNode#end_keyword_loc
     *
     * The location of the `end` keyword.
     *
     *     for i in a end
     *                ^^^
     */
    pm_location_t end_keyword_loc;
} pm_for_node_t;

/**
 * ForwardingArgumentsNode
 *
 * Represents forwarding all arguments to this method to another method.
 *
 *     def foo(...)
 *       bar(...)
 *           ^^^
 *     end
 *
 * Type: ::PM_FORWARDING_ARGUMENTS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_forwarding_arguments_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_forwarding_arguments_node_t;

/**
 * ForwardingParameterNode
 *
 * Represents the use of the forwarding parameter in a method, block, or lambda declaration.
 *
 *     def foo(...)
 *             ^^^
 *     end
 *
 * Type: ::PM_FORWARDING_PARAMETER_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_forwarding_parameter_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_forwarding_parameter_node_t;

/**
 * ForwardingSuperNode
 *
 * Represents the use of the `super` keyword without parentheses or arguments, but which might have a block.
 *
 *     super
 *     ^^^^^
 *
 *     super { 123 }
 *     ^^^^^^^^^^^^^
 *
 * If it has any other arguments, it would be a `SuperNode` instead.
 *
 * Type: ::PM_FORWARDING_SUPER_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_forwarding_super_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ForwardingSuperNode#block
     *
     * All other arguments are forwarded as normal, except the original block is replaced with the new block.
     */
    struct pm_block_node *block;
} pm_forwarding_super_node_t;

/**
 * GlobalVariableAndWriteNode
 *
 * Represents the use of the `&&=` operator for assignment to a global variable.
 *
 *     $target &&= value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_GLOBAL_VARIABLE_AND_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_global_variable_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * GlobalVariableAndWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * GlobalVariableAndWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * GlobalVariableAndWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * GlobalVariableAndWriteNode#value
     */
    struct pm_node *value;
} pm_global_variable_and_write_node_t;

/**
 * GlobalVariableOperatorWriteNode
 *
 * Represents assigning to a global variable using an operator that isn't `=`.
 *
 *     $target += value
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_global_variable_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * GlobalVariableOperatorWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * GlobalVariableOperatorWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * GlobalVariableOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * GlobalVariableOperatorWriteNode#value
     */
    struct pm_node *value;

    /**
     * GlobalVariableOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;
} pm_global_variable_operator_write_node_t;

/**
 * GlobalVariableOrWriteNode
 *
 * Represents the use of the `||=` operator for assignment to a global variable.
 *
 *     $target ||= value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_GLOBAL_VARIABLE_OR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_global_variable_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * GlobalVariableOrWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * GlobalVariableOrWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * GlobalVariableOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * GlobalVariableOrWriteNode#value
     */
    struct pm_node *value;
} pm_global_variable_or_write_node_t;

/**
 * GlobalVariableReadNode
 *
 * Represents referencing a global variable.
 *
 *     $foo
 *     ^^^^
 *
 * Type: ::PM_GLOBAL_VARIABLE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_global_variable_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * GlobalVariableReadNode#name
     *
     * The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol.
     *
     *     $foo   # name `:$foo`
     *
     *     $_Test # name `:$_Test`
     */
    pm_constant_id_t name;
} pm_global_variable_read_node_t;

/**
 * GlobalVariableTargetNode
 *
 * Represents writing to a global variable in a context that doesn't have an explicit value.
 *
 *     $foo, $bar = baz
 *     ^^^^  ^^^^
 *
 * Type: ::PM_GLOBAL_VARIABLE_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_global_variable_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * GlobalVariableTargetNode#name
     */
    pm_constant_id_t name;
} pm_global_variable_target_node_t;

/**
 * GlobalVariableWriteNode
 *
 * Represents writing to a global variable.
 *
 *     $foo = 1
 *     ^^^^^^^^
 *
 * Type: ::PM_GLOBAL_VARIABLE_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_global_variable_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * GlobalVariableWriteNode#name
     *
     * The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol.
     *
     *     $foo = :bar  # name `:$foo`
     *
     *     $_Test = 123 # name `:$_Test`
     */
    pm_constant_id_t name;

    /**
     * GlobalVariableWriteNode#name_loc
     *
     * The location of the global variable's name.
     *
     *     $foo = :bar
     *     ^^^^
     */
    pm_location_t name_loc;

    /**
     * GlobalVariableWriteNode#value
     *
     * The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     $foo = :bar
     *            ^^^^
     *
     *     $-xyz = 123
     *             ^^^
     */
    struct pm_node *value;

    /**
     * GlobalVariableWriteNode#operator_loc
     *
     * The location of the `=` operator.
     *
     *     $foo = :bar
     *          ^
     */
    pm_location_t operator_loc;
} pm_global_variable_write_node_t;

/**
 * HashNode
 *
 * Represents a hash literal.
 *
 *     { a => b }
 *     ^^^^^^^^^^
 *
 * Type: ::PM_HASH_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_hash_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * HashNode#opening_loc
     *
     * The location of the opening brace.
     *
     *     { a => b }
     *     ^
     */
    pm_location_t opening_loc;

    /**
     * HashNode#elements
     *
     * The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s.
     *
     *     { a: b }
     *       ^^^^
     *
     *     { **foo }
     *       ^^^^^
     */
    struct pm_node_list elements;

    /**
     * HashNode#closing_loc
     *
     * The location of the closing brace.
     *
     *     { a => b }
     *              ^
     */
    pm_location_t closing_loc;
} pm_hash_node_t;

/**
 * HashPatternNode
 *
 * Represents a hash pattern in pattern matching.
 *
 *     foo => { a: 1, b: 2 }
 *            ^^^^^^^^^^^^^^
 *
 *     foo => { a: 1, b: 2, **c }
 *            ^^^^^^^^^^^^^^^^^^^
 *
 *     foo => Bar[a: 1, b: 2]
 *            ^^^^^^^^^^^^^^^
 *
 *     foo in { a: 1, b: 2 }
 *            ^^^^^^^^^^^^^^
 *
 * Type: ::PM_HASH_PATTERN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_hash_pattern_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * HashPatternNode#constant
     *
     * Represents the optional constant preceding the Hash.
     *
     *     foo => Bar[a: 1, b: 2]
     *          ^^^
     *
     *     foo => Bar::Baz[a: 1, b: 2]
     *          ^^^^^^^^
     */
    struct pm_node *constant;

    /**
     * HashPatternNode#elements
     *
     * Represents the explicit named hash keys and values.
     *
     *     foo => { a: 1, b:, ** }
     *              ^^^^^^^^
     */
    struct pm_node_list elements;

    /**
     * HashPatternNode#rest
     *
     * Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`.
     *
     *     foo => { a: 1, b:, **c }
     *                        ^^^
     *
     *     foo => { a: 1, b:, ** }
     *                        ^^
     *
     *     foo => { a: 1, b:, **nil }
     *                        ^^^^^
     */
    struct pm_node *rest;

    /**
     * HashPatternNode#opening_loc
     *
     * The location of the opening brace.
     *
     *     foo => { a: 1 }
     *            ^
     *
     *     foo => Bar[a: 1]
     *               ^
     */
    pm_location_t opening_loc;

    /**
     * HashPatternNode#closing_loc
     *
     * The location of the closing brace.
     *
     *     foo => { a: 1 }
     *                   ^
     *
     *     foo => Bar[a: 1]
     *                    ^
     */
    pm_location_t closing_loc;
} pm_hash_pattern_node_t;

/**
 * IfNode
 *
 * Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression.
 *
 *     bar if foo
 *     ^^^^^^^^^^
 *
 *     if foo then bar end
 *     ^^^^^^^^^^^^^^^^^^^
 *
 *     foo ? bar : baz
 *     ^^^^^^^^^^^^^^^
 *
 * Type: ::PM_IF_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_if_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * IfNode#if_keyword_loc
     *
     * The location of the `if` keyword if present.
     *
     *     bar if foo
     *         ^^
     *
     * The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression.
     */
    pm_location_t if_keyword_loc;

    /**
     * IfNode#predicate
     *
     * The node for the condition the `IfNode` is testing.
     *
     *     if foo
     *        ^^^
     *       bar
     *     end
     *
     *     bar if foo
     *            ^^^
     *
     *     foo ? bar : baz
     *     ^^^
     */
    struct pm_node *predicate;

    /**
     * IfNode#then_keyword_loc
     *
     * The location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise.
     *
     *     if foo then bar end
     *            ^^^^
     *
     *     a ? b : c
     *       ^
     */
    pm_location_t then_keyword_loc;

    /**
     * IfNode#statements
     *
     * Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided.
     *
     *     if foo
     *       bar
     *       ^^^
     *       baz
     *       ^^^
     *     end
     */
    struct pm_statements_node *statements;

    /**
     * IfNode#subsequent
     *
     * Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement.
     *
     *     if foo
     *       bar
     *     elsif baz
     *     ^^^^^^^^^
     *       qux
     *       ^^^
     *     end
     *     ^^^
     *
     *     if foo then bar else baz end
     *                     ^^^^^^^^^^^^
     */
    struct pm_node *subsequent;

    /**
     * IfNode#end_keyword_loc
     *
     * The location of the `end` keyword if present, `nil` otherwise.
     *
     *     if foo
     *       bar
     *     end
     *     ^^^
     */
    pm_location_t end_keyword_loc;
} pm_if_node_t;

/**
 * ImaginaryNode
 *
 * Represents an imaginary number literal.
 *
 *     1.0i
 *     ^^^^
 *
 * Type: ::PM_IMAGINARY_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_imaginary_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ImaginaryNode#numeric
     */
    struct pm_node *numeric;
} pm_imaginary_node_t;

/**
 * ImplicitNode
 *
 * Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source.
 *
 *     { foo: }
 *       ^^^^
 *
 *     { Foo: }
 *       ^^^^
 *
 *     foo in { bar: }
 *              ^^^^
 *
 * Type: ::PM_IMPLICIT_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_implicit_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ImplicitNode#value
     */
    struct pm_node *value;
} pm_implicit_node_t;

/**
 * ImplicitRestNode
 *
 * Represents using a trailing comma to indicate an implicit rest parameter.
 *
 *     foo { |bar,| }
 *               ^
 *
 *     foo in [bar,]
 *                ^
 *
 *     for foo, in bar do end
 *            ^
 *
 *     foo, = bar
 *        ^
 *
 * Type: ::PM_IMPLICIT_REST_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_implicit_rest_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_implicit_rest_node_t;

/**
 * InNode
 *
 * Represents the use of the `in` keyword in a case statement.
 *
 *     case a; in b then c end
 *             ^^^^^^^^^^^
 *
 * Type: ::PM_IN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_in_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InNode#pattern
     */
    struct pm_node *pattern;

    /**
     * InNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * InNode#in_loc
     */
    pm_location_t in_loc;

    /**
     * InNode#then_loc
     */
    pm_location_t then_loc;
} pm_in_node_t;

/**
 * IndexAndWriteNode
 *
 * Represents the use of the `&&=` operator on a call to the `[]` method.
 *
 *     foo.bar[baz] &&= value
 *     ^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INDEX_AND_WRITE_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_index_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * IndexAndWriteNode#receiver
     */
    struct pm_node *receiver;

    /**
     * IndexAndWriteNode#call_operator_loc
     */
    pm_location_t call_operator_loc;

    /**
     * IndexAndWriteNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * IndexAndWriteNode#arguments
     */
    struct pm_arguments_node *arguments;

    /**
     * IndexAndWriteNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * IndexAndWriteNode#block
     */
    struct pm_block_argument_node *block;

    /**
     * IndexAndWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * IndexAndWriteNode#value
     */
    struct pm_node *value;
} pm_index_and_write_node_t;

/**
 * IndexOperatorWriteNode
 *
 * Represents the use of an assignment operator on a call to `[]`.
 *
 *     foo.bar[baz] += value
 *     ^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INDEX_OPERATOR_WRITE_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_index_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * IndexOperatorWriteNode#receiver
     */
    struct pm_node *receiver;

    /**
     * IndexOperatorWriteNode#call_operator_loc
     */
    pm_location_t call_operator_loc;

    /**
     * IndexOperatorWriteNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * IndexOperatorWriteNode#arguments
     */
    struct pm_arguments_node *arguments;

    /**
     * IndexOperatorWriteNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * IndexOperatorWriteNode#block
     */
    struct pm_block_argument_node *block;

    /**
     * IndexOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;

    /**
     * IndexOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * IndexOperatorWriteNode#value
     */
    struct pm_node *value;
} pm_index_operator_write_node_t;

/**
 * IndexOrWriteNode
 *
 * Represents the use of the `||=` operator on a call to `[]`.
 *
 *     foo.bar[baz] ||= value
 *     ^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INDEX_OR_WRITE_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_index_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * IndexOrWriteNode#receiver
     */
    struct pm_node *receiver;

    /**
     * IndexOrWriteNode#call_operator_loc
     */
    pm_location_t call_operator_loc;

    /**
     * IndexOrWriteNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * IndexOrWriteNode#arguments
     */
    struct pm_arguments_node *arguments;

    /**
     * IndexOrWriteNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * IndexOrWriteNode#block
     */
    struct pm_block_argument_node *block;

    /**
     * IndexOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * IndexOrWriteNode#value
     */
    struct pm_node *value;
} pm_index_or_write_node_t;

/**
 * IndexTargetNode
 *
 * Represents assigning to an index.
 *
 *     foo[bar], = 1
 *     ^^^^^^^^
 *
 *     begin
 *     rescue => foo[bar]
 *               ^^^^^^^^
 *     end
 *
 *     for foo[bar] in baz do end
 *         ^^^^^^^^
 *
 * Type: ::PM_INDEX_TARGET_NODE

 * Flags (#pm_call_node_flags):
 * * ::PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
 * * ::PM_CALL_NODE_FLAGS_VARIABLE_CALL
 * * ::PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
 * * ::PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY
 *
 * @extends pm_node_t
 */
typedef struct pm_index_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * IndexTargetNode#receiver
     */
    struct pm_node *receiver;

    /**
     * IndexTargetNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * IndexTargetNode#arguments
     */
    struct pm_arguments_node *arguments;

    /**
     * IndexTargetNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * IndexTargetNode#block
     */
    struct pm_block_argument_node *block;
} pm_index_target_node_t;

/**
 * InstanceVariableAndWriteNode
 *
 * Represents the use of the `&&=` operator for assignment to an instance variable.
 *
 *     @target &&= value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INSTANCE_VARIABLE_AND_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_instance_variable_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InstanceVariableAndWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * InstanceVariableAndWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * InstanceVariableAndWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * InstanceVariableAndWriteNode#value
     */
    struct pm_node *value;
} pm_instance_variable_and_write_node_t;

/**
 * InstanceVariableOperatorWriteNode
 *
 * Represents assigning to an instance variable using an operator that isn't `=`.
 *
 *     @target += value
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_instance_variable_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InstanceVariableOperatorWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * InstanceVariableOperatorWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * InstanceVariableOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * InstanceVariableOperatorWriteNode#value
     */
    struct pm_node *value;

    /**
     * InstanceVariableOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;
} pm_instance_variable_operator_write_node_t;

/**
 * InstanceVariableOrWriteNode
 *
 * Represents the use of the `||=` operator for assignment to an instance variable.
 *
 *     @target ||= value
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INSTANCE_VARIABLE_OR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_instance_variable_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InstanceVariableOrWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * InstanceVariableOrWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * InstanceVariableOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * InstanceVariableOrWriteNode#value
     */
    struct pm_node *value;
} pm_instance_variable_or_write_node_t;

/**
 * InstanceVariableReadNode
 *
 * Represents referencing an instance variable.
 *
 *     @foo
 *     ^^^^
 *
 * Type: ::PM_INSTANCE_VARIABLE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_instance_variable_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InstanceVariableReadNode#name
     *
     * The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     @x     # name `:@x`
     *
     *     @_test # name `:@_test`
     */
    pm_constant_id_t name;
} pm_instance_variable_read_node_t;

/**
 * InstanceVariableTargetNode
 *
 * Represents writing to an instance variable in a context that doesn't have an explicit value.
 *
 *     @foo, @bar = baz
 *     ^^^^  ^^^^
 *
 * Type: ::PM_INSTANCE_VARIABLE_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_instance_variable_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InstanceVariableTargetNode#name
     */
    pm_constant_id_t name;
} pm_instance_variable_target_node_t;

/**
 * InstanceVariableWriteNode
 *
 * Represents writing to an instance variable.
 *
 *     @foo = 1
 *     ^^^^^^^^
 *
 * Type: ::PM_INSTANCE_VARIABLE_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_instance_variable_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InstanceVariableWriteNode#name
     *
     * The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     @x = :y       # name `:@x`
     *
     *     @_foo = "bar" # name `@_foo`
     */
    pm_constant_id_t name;

    /**
     * InstanceVariableWriteNode#name_loc
     *
     * The location of the variable name.
     *
     *     @_x = 1
     *     ^^^
     */
    pm_location_t name_loc;

    /**
     * InstanceVariableWriteNode#value
     *
     * The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     @foo = :bar
     *            ^^^^
     *
     *     @_x = 1234
     *           ^^^^
     */
    struct pm_node *value;

    /**
     * InstanceVariableWriteNode#operator_loc
     *
     * The location of the `=` operator.
     *
     *     @x = y
     *        ^
     */
    pm_location_t operator_loc;
} pm_instance_variable_write_node_t;

/**
 * IntegerNode
 *
 * Represents an integer number literal.
 *
 *     1
 *     ^
 *
 * Type: ::PM_INTEGER_NODE

 * Flags (#pm_integer_base_flags):
 * * ::PM_INTEGER_BASE_FLAGS_BINARY
 * * ::PM_INTEGER_BASE_FLAGS_DECIMAL
 * * ::PM_INTEGER_BASE_FLAGS_OCTAL
 * * ::PM_INTEGER_BASE_FLAGS_HEXADECIMAL
 *
 * @extends pm_node_t
 */
typedef struct pm_integer_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * IntegerNode#value
     *
     * The value of the integer literal as a number.
     */
    pm_integer_t value;
} pm_integer_node_t;

/**
 * InterpolatedMatchLastLineNode
 *
 * Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object.
 *
 *     if /foo #{bar} baz/ then end
 *        ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INTERPOLATED_MATCH_LAST_LINE_NODE

 * Flags (#pm_regular_expression_flags):
 * * ::PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EXTENDED
 * * ::PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ONCE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EUC_JP
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT
 * * ::PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J
 * * ::PM_REGULAR_EXPRESSION_FLAGS_UTF_8
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING
 *
 * @extends pm_node_t
 */
typedef struct pm_interpolated_match_last_line_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InterpolatedMatchLastLineNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * InterpolatedMatchLastLineNode#parts
     */
    struct pm_node_list parts;

    /**
     * InterpolatedMatchLastLineNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_interpolated_match_last_line_node_t;

/**
 * InterpolatedRegularExpressionNode
 *
 * Represents a regular expression literal that contains interpolation.
 *
 *     /foo #{bar} baz/
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INTERPOLATED_REGULAR_EXPRESSION_NODE

 * Flags (#pm_regular_expression_flags):
 * * ::PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EXTENDED
 * * ::PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ONCE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EUC_JP
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT
 * * ::PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J
 * * ::PM_REGULAR_EXPRESSION_FLAGS_UTF_8
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING
 *
 * @extends pm_node_t
 */
typedef struct pm_interpolated_regular_expression_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InterpolatedRegularExpressionNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * InterpolatedRegularExpressionNode#parts
     */
    struct pm_node_list parts;

    /**
     * InterpolatedRegularExpressionNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_interpolated_regular_expression_node_t;

/**
 * InterpolatedStringNode
 *
 * Represents a string literal that contains interpolation.
 *
 *     "foo #{bar} baz"
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INTERPOLATED_STRING_NODE

 * Flags (#pm_interpolated_string_node_flags):
 * * ::PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN
 * * ::PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE
 *
 * @extends pm_node_t
 */
typedef struct pm_interpolated_string_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InterpolatedStringNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * InterpolatedStringNode#parts
     */
    struct pm_node_list parts;

    /**
     * InterpolatedStringNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_interpolated_string_node_t;

/**
 * InterpolatedSymbolNode
 *
 * Represents a symbol literal that contains interpolation.
 *
 *     :"foo #{bar} baz"
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INTERPOLATED_SYMBOL_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_interpolated_symbol_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InterpolatedSymbolNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * InterpolatedSymbolNode#parts
     */
    struct pm_node_list parts;

    /**
     * InterpolatedSymbolNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_interpolated_symbol_node_t;

/**
 * InterpolatedXStringNode
 *
 * Represents an xstring literal that contains interpolation.
 *
 *     `foo #{bar} baz`
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_INTERPOLATED_X_STRING_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_interpolated_x_string_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * InterpolatedXStringNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * InterpolatedXStringNode#parts
     */
    struct pm_node_list parts;

    /**
     * InterpolatedXStringNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_interpolated_x_string_node_t;

/**
 * ItLocalVariableReadNode
 *
 * Represents reading from the implicit `it` local variable.
 *
 *     -> { it }
 *          ^^
 *
 * Type: ::PM_IT_LOCAL_VARIABLE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_it_local_variable_read_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_it_local_variable_read_node_t;

/**
 * ItParametersNode
 *
 * Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda.
 *
 *     -> { it + it }
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_IT_PARAMETERS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_it_parameters_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_it_parameters_node_t;

/**
 * KeywordHashNode
 *
 * Represents a hash literal without opening and closing braces.
 *
 *     foo(a: b)
 *         ^^^^
 *
 * Type: ::PM_KEYWORD_HASH_NODE

 * Flags (#pm_keyword_hash_node_flags):
 * * ::PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS
 *
 * @extends pm_node_t
 */
typedef struct pm_keyword_hash_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * KeywordHashNode#elements
     */
    struct pm_node_list elements;
} pm_keyword_hash_node_t;

/**
 * KeywordRestParameterNode
 *
 * Represents a keyword rest parameter to a method, block, or lambda definition.
 *
 *     def a(**b)
 *           ^^^
 *     end
 *
 * Type: ::PM_KEYWORD_REST_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_keyword_rest_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * KeywordRestParameterNode#name
     */
    pm_constant_id_t name;

    /**
     * KeywordRestParameterNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * KeywordRestParameterNode#operator_loc
     */
    pm_location_t operator_loc;
} pm_keyword_rest_parameter_node_t;

/**
 * LambdaNode
 *
 * Represents using a lambda literal (not the lambda method call).
 *
 *     ->(value) { value * 2 }
 *     ^^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_LAMBDA_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_lambda_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LambdaNode#locals
     */
    pm_constant_id_list_t locals;

    /**
     * LambdaNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * LambdaNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * LambdaNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * LambdaNode#parameters
     */
    struct pm_node *parameters;

    /**
     * LambdaNode#body
     */
    struct pm_node *body;
} pm_lambda_node_t;

/**
 * LocalVariableAndWriteNode
 *
 * Represents the use of the `&&=` operator for assignment to a local variable.
 *
 *     target &&= value
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_LOCAL_VARIABLE_AND_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_local_variable_and_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LocalVariableAndWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * LocalVariableAndWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * LocalVariableAndWriteNode#value
     */
    struct pm_node *value;

    /**
     * LocalVariableAndWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * LocalVariableAndWriteNode#depth
     */
    uint32_t depth;
} pm_local_variable_and_write_node_t;

/**
 * LocalVariableOperatorWriteNode
 *
 * Represents assigning to a local variable using an operator that isn't `=`.
 *
 *     target += value
 *     ^^^^^^^^^^^^^^^
 *
 * Type: ::PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_local_variable_operator_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LocalVariableOperatorWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * LocalVariableOperatorWriteNode#binary_operator_loc
     */
    pm_location_t binary_operator_loc;

    /**
     * LocalVariableOperatorWriteNode#value
     */
    struct pm_node *value;

    /**
     * LocalVariableOperatorWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * LocalVariableOperatorWriteNode#binary_operator
     */
    pm_constant_id_t binary_operator;

    /**
     * LocalVariableOperatorWriteNode#depth
     */
    uint32_t depth;
} pm_local_variable_operator_write_node_t;

/**
 * LocalVariableOrWriteNode
 *
 * Represents the use of the `||=` operator for assignment to a local variable.
 *
 *     target ||= value
 *     ^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_LOCAL_VARIABLE_OR_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_local_variable_or_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LocalVariableOrWriteNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * LocalVariableOrWriteNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * LocalVariableOrWriteNode#value
     */
    struct pm_node *value;

    /**
     * LocalVariableOrWriteNode#name
     */
    pm_constant_id_t name;

    /**
     * LocalVariableOrWriteNode#depth
     */
    uint32_t depth;
} pm_local_variable_or_write_node_t;

/**
 * LocalVariableReadNode
 *
 * Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call.
 *
 *     foo
 *     ^^^
 *
 * Type: ::PM_LOCAL_VARIABLE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_local_variable_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LocalVariableReadNode#name
     *
     * The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     x      # name `:x`
     *
     *     _Test  # name `:_Test`
     *
     * Note that this can also be an underscore followed by a number for the default block parameters.
     *
     *     _1     # name `:_1`
     */
    pm_constant_id_t name;

    /**
     * LocalVariableReadNode#depth
     *
     * The number of visible scopes that should be searched to find the origin of this local variable.
     *
     *     foo = 1; foo # depth 0
     *
     *     bar = 2; tap { bar } # depth 1
     *
     * The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md).
     */
    uint32_t depth;
} pm_local_variable_read_node_t;

/**
 * LocalVariableTargetNode
 *
 * Represents writing to a local variable in a context that doesn't have an explicit value.
 *
 *     foo, bar = baz
 *     ^^^  ^^^
 *
 *     foo => baz
 *            ^^^
 *
 * Type: ::PM_LOCAL_VARIABLE_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_local_variable_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LocalVariableTargetNode#name
     */
    pm_constant_id_t name;

    /**
     * LocalVariableTargetNode#depth
     */
    uint32_t depth;
} pm_local_variable_target_node_t;

/**
 * LocalVariableWriteNode
 *
 * Represents writing to a local variable.
 *
 *     foo = 1
 *     ^^^^^^^
 *
 * Type: ::PM_LOCAL_VARIABLE_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_local_variable_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * LocalVariableWriteNode#name
     *
     * The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
     *
     *     foo = :bar # name `:foo`
     *
     *     abc = 123  # name `:abc`
     */
    pm_constant_id_t name;

    /**
     * LocalVariableWriteNode#depth
     *
     * The number of semantic scopes we have to traverse to find the declaration of this variable.
     *
     *     foo = 1         # depth 0
     *
     *     tap { foo = 1 } # depth 1
     *
     * The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md).
     */
    uint32_t depth;

    /**
     * LocalVariableWriteNode#name_loc
     *
     * The location of the variable name.
     *
     *     foo = :bar
     *     ^^^
     */
    pm_location_t name_loc;

    /**
     * LocalVariableWriteNode#value
     *
     * The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     foo = :bar
     *           ^^^^
     *
     *     abc = 1234
     *           ^^^^
     *
     * Note that since the name of a local variable is known before the value is parsed, it is valid for a local variable to appear within the value of its own write.
     *
     *     foo = foo
     */
    struct pm_node *value;

    /**
     * LocalVariableWriteNode#operator_loc
     *
     * The location of the `=` operator.
     *
     *     x = :y
     *       ^
     */
    pm_location_t operator_loc;
} pm_local_variable_write_node_t;

/**
 * MatchLastLineNode
 *
 * Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object.
 *
 *     if /foo/i then end
 *        ^^^^^^
 *
 * Type: ::PM_MATCH_LAST_LINE_NODE

 * Flags (#pm_regular_expression_flags):
 * * ::PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EXTENDED
 * * ::PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ONCE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EUC_JP
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT
 * * ::PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J
 * * ::PM_REGULAR_EXPRESSION_FLAGS_UTF_8
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING
 *
 * @extends pm_node_t
 */
typedef struct pm_match_last_line_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * MatchLastLineNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * MatchLastLineNode#content_loc
     */
    pm_location_t content_loc;

    /**
     * MatchLastLineNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * MatchLastLineNode#unescaped
     */
    pm_string_t unescaped;
} pm_match_last_line_node_t;

/**
 * MatchPredicateNode
 *
 * Represents the use of the modifier `in` operator.
 *
 *     foo in bar
 *     ^^^^^^^^^^
 *
 * Type: ::PM_MATCH_PREDICATE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_match_predicate_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * MatchPredicateNode#value
     */
    struct pm_node *value;

    /**
     * MatchPredicateNode#pattern
     */
    struct pm_node *pattern;

    /**
     * MatchPredicateNode#operator_loc
     */
    pm_location_t operator_loc;
} pm_match_predicate_node_t;

/**
 * MatchRequiredNode
 *
 * Represents the use of the `=>` operator.
 *
 *     foo => bar
 *     ^^^^^^^^^^
 *
 * Type: ::PM_MATCH_REQUIRED_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_match_required_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * MatchRequiredNode#value
     *
     * Represents the left-hand side of the operator.
     *
     *     foo => bar
     *     ^^^
     */
    struct pm_node *value;

    /**
     * MatchRequiredNode#pattern
     *
     * Represents the right-hand side of the operator. The type of the node depends on the expression.
     *
     * Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`.
     *
     *     foo => a # This is equivalent to writing `a = foo`
     *            ^
     *
     * Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant.
     *
     *     foo => [a]
     *            ^^^
     *
     *     foo => a, b
     *            ^^^^
     *
     *     foo => Bar[a, b]
     *            ^^^^^^^^^
     *
     * If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead.
     *
     *     foo => *, 1, *a
     *            ^^^^^
     *
     * Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`.
     *
     *     foo => { a: 1, b: }
     *
     *     foo => Bar[a: 1, b:]
     *
     *     foo => Bar[**]
     *
     * To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode`
     *
     *     foo => ^a
     *            ^^
     *
     * Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`.
     *
     *     foo => ^(a + 1)
     *
     * Anything else will result in the regular node for that expression, for example a `ConstantReadNode`.
     *
     *     foo => CONST
     */
    struct pm_node *pattern;

    /**
     * MatchRequiredNode#operator_loc
     *
     * The location of the operator.
     *
     *     foo => bar
     *         ^^
     */
    pm_location_t operator_loc;
} pm_match_required_node_t;

/**
 * MatchWriteNode
 *
 * Represents writing local variables using a regular expression match with named capture groups.
 *
 *     /(?<foo>bar)/ =~ baz
 *     ^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_MATCH_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_match_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * MatchWriteNode#call
     */
    struct pm_call_node *call;

    /**
     * MatchWriteNode#targets
     */
    struct pm_node_list targets;
} pm_match_write_node_t;

/**
 * MissingNode
 *
 * Represents a node that is missing from the source and results in a syntax error.
 *
 * Type: ::PM_MISSING_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_missing_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_missing_node_t;

/**
 * ModuleNode
 *
 * Represents a module declaration involving the `module` keyword.
 *
 *     module Foo end
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_MODULE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_module_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ModuleNode#locals
     */
    pm_constant_id_list_t locals;

    /**
     * ModuleNode#module_keyword_loc
     */
    pm_location_t module_keyword_loc;

    /**
     * ModuleNode#constant_path
     */
    struct pm_node *constant_path;

    /**
     * ModuleNode#body
     */
    struct pm_node *body;

    /**
     * ModuleNode#end_keyword_loc
     */
    pm_location_t end_keyword_loc;

    /**
     * ModuleNode#name
     */
    pm_constant_id_t name;
} pm_module_node_t;

/**
 * MultiTargetNode
 *
 * Represents a multi-target expression.
 *
 *     a, (b, c) = 1, 2, 3
 *        ^^^^^^
 *
 * This can be a part of `MultiWriteNode` as above, or the target of a `for` loop
 *
 *     for a, b in [[1, 2], [3, 4]]
 *         ^^^^
 *
 * Type: ::PM_MULTI_TARGET_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_multi_target_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * MultiTargetNode#lefts
     *
     * Represents the targets expressions before a splat node.
     *
     *     a, (b, c, *) = 1, 2, 3, 4, 5
     *         ^^^^
     *
     * The splat node can be absent, in that case all target expressions are in the left field.
     *
     *     a, (b, c) = 1, 2, 3, 4, 5
     *         ^^^^
     */
    struct pm_node_list lefts;

    /**
     * MultiTargetNode#rest
     *
     * Represents a splat node in the target expression.
     *
     *     a, (b, *c) = 1, 2, 3, 4
     *            ^^
     *
     * The variable can be empty, this results in a `SplatNode` with a `nil` expression field.
     *
     *     a, (b, *) = 1, 2, 3, 4
     *            ^
     *
     * If the `*` is omitted, this field will contain an `ImplicitRestNode`
     *
     *     a, (b,) = 1, 2, 3, 4
     *          ^
     */
    struct pm_node *rest;

    /**
     * MultiTargetNode#rights
     *
     * Represents the targets expressions after a splat node.
     *
     *     a, (*, b, c) = 1, 2, 3, 4, 5
     *            ^^^^
     */
    struct pm_node_list rights;

    /**
     * MultiTargetNode#lparen_loc
     *
     * The location of the opening parenthesis.
     *
     *     a, (b, c) = 1, 2, 3
     *        ^
     */
    pm_location_t lparen_loc;

    /**
     * MultiTargetNode#rparen_loc
     *
     * The location of the closing parenthesis.
     *
     *     a, (b, c) = 1, 2, 3
     *             ^
     */
    pm_location_t rparen_loc;
} pm_multi_target_node_t;

/**
 * MultiWriteNode
 *
 * Represents a write to a multi-target expression.
 *
 *     a, b, c = 1, 2, 3
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_MULTI_WRITE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_multi_write_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * MultiWriteNode#lefts
     *
     * Represents the targets expressions before a splat node.
     *
     *     a, b, * = 1, 2, 3, 4, 5
     *     ^^^^
     *
     * The splat node can be absent, in that case all target expressions are in the left field.
     *
     *     a, b, c = 1, 2, 3, 4, 5
     *     ^^^^^^^
     */
    struct pm_node_list lefts;

    /**
     * MultiWriteNode#rest
     *
     * Represents a splat node in the target expression.
     *
     *     a, b, *c = 1, 2, 3, 4
     *           ^^
     *
     * The variable can be empty, this results in a `SplatNode` with a `nil` expression field.
     *
     *     a, b, * = 1, 2, 3, 4
     *           ^
     *
     * If the `*` is omitted, this field will contain an `ImplicitRestNode`
     *
     *     a, b, = 1, 2, 3, 4
     *         ^
     */
    struct pm_node *rest;

    /**
     * MultiWriteNode#rights
     *
     * Represents the targets expressions after a splat node.
     *
     *     a, *, b, c = 1, 2, 3, 4, 5
     *           ^^^^
     */
    struct pm_node_list rights;

    /**
     * MultiWriteNode#lparen_loc
     *
     * The location of the opening parenthesis.
     *
     *     (a, b, c) = 1, 2, 3
     *     ^
     */
    pm_location_t lparen_loc;

    /**
     * MultiWriteNode#rparen_loc
     *
     * The location of the closing parenthesis.
     *
     *     (a, b, c) = 1, 2, 3
     *             ^
     */
    pm_location_t rparen_loc;

    /**
     * MultiWriteNode#operator_loc
     *
     * The location of the operator.
     *
     *     a, b, c = 1, 2, 3
     *             ^
     */
    pm_location_t operator_loc;

    /**
     * MultiWriteNode#value
     *
     * The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     a, b, c = 1, 2, 3
     *               ^^^^^^^
     */
    struct pm_node *value;
} pm_multi_write_node_t;

/**
 * NextNode
 *
 * Represents the use of the `next` keyword.
 *
 *     next 1
 *     ^^^^^^
 *
 * Type: ::PM_NEXT_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_next_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * NextNode#arguments
     */
    struct pm_arguments_node *arguments;

    /**
     * NextNode#keyword_loc
     */
    pm_location_t keyword_loc;
} pm_next_node_t;

/**
 * NilNode
 *
 * Represents the use of the `nil` keyword.
 *
 *     nil
 *     ^^^
 *
 * Type: ::PM_NIL_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_nil_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_nil_node_t;

/**
 * NoKeywordsParameterNode
 *
 * Represents the use of `**nil` inside method arguments.
 *
 *     def a(**nil)
 *           ^^^^^
 *     end
 *
 * Type: ::PM_NO_KEYWORDS_PARAMETER_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_no_keywords_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * NoKeywordsParameterNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * NoKeywordsParameterNode#keyword_loc
     */
    pm_location_t keyword_loc;
} pm_no_keywords_parameter_node_t;

/**
 * NumberedParametersNode
 *
 * Represents an implicit set of parameters through the use of numbered parameters within a block or lambda.
 *
 *     -> { _1 + _2 }
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_NUMBERED_PARAMETERS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_numbered_parameters_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * NumberedParametersNode#maximum
     */
    uint8_t maximum;
} pm_numbered_parameters_node_t;

/**
 * NumberedReferenceReadNode
 *
 * Represents reading a numbered reference to a capture in the previous match.
 *
 *     $1
 *     ^^
 *
 * Type: ::PM_NUMBERED_REFERENCE_READ_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_numbered_reference_read_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * NumberedReferenceReadNode#number
     *
     * The (1-indexed, from the left) number of the capture group. Numbered references that are too large result in this value being `0`.
     *
     *     $1          # number `1`
     *
     *     $5432       # number `5432`
     *
     *     $4294967296 # number `0`
     */
    uint32_t number;
} pm_numbered_reference_read_node_t;

/**
 * OptionalKeywordParameterNode
 *
 * Represents an optional keyword parameter to a method, block, or lambda definition.
 *
 *     def a(b: 1)
 *           ^^^^
 *     end
 *
 * Type: ::PM_OPTIONAL_KEYWORD_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_optional_keyword_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * OptionalKeywordParameterNode#name
     */
    pm_constant_id_t name;

    /**
     * OptionalKeywordParameterNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * OptionalKeywordParameterNode#value
     */
    struct pm_node *value;
} pm_optional_keyword_parameter_node_t;

/**
 * OptionalParameterNode
 *
 * Represents an optional parameter to a method, block, or lambda definition.
 *
 *     def a(b = 1)
 *           ^^^^^
 *     end
 *
 * Type: ::PM_OPTIONAL_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_optional_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * OptionalParameterNode#name
     */
    pm_constant_id_t name;

    /**
     * OptionalParameterNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * OptionalParameterNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * OptionalParameterNode#value
     */
    struct pm_node *value;
} pm_optional_parameter_node_t;

/**
 * OrNode
 *
 * Represents the use of the `||` operator or the `or` keyword.
 *
 *     left or right
 *     ^^^^^^^^^^^^^
 *
 * Type: ::PM_OR_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_or_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * OrNode#left
     *
     * Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     left or right
     *     ^^^^
     *
     *     1 || 2
     *     ^
     */
    struct pm_node *left;

    /**
     * OrNode#right
     *
     * Represents the right side of the expression.
     *
     *     left || right
     *             ^^^^^
     *
     *     1 or 2
     *          ^
     */
    struct pm_node *right;

    /**
     * OrNode#operator_loc
     *
     * The location of the `or` keyword or the `||` operator.
     *
     *     left or right
     *          ^^
     */
    pm_location_t operator_loc;
} pm_or_node_t;

/**
 * ParametersNode
 *
 * Represents the list of parameters on a method, block, or lambda definition.
 *
 *     def a(b, c, d)
 *           ^^^^^^^
 *     end
 *
 * Type: ::PM_PARAMETERS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_parameters_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ParametersNode#requireds
     */
    struct pm_node_list requireds;

    /**
     * ParametersNode#optionals
     */
    struct pm_node_list optionals;

    /**
     * ParametersNode#rest
     */
    struct pm_node *rest;

    /**
     * ParametersNode#posts
     */
    struct pm_node_list posts;

    /**
     * ParametersNode#keywords
     */
    struct pm_node_list keywords;

    /**
     * ParametersNode#keyword_rest
     */
    struct pm_node *keyword_rest;

    /**
     * ParametersNode#block
     */
    struct pm_block_parameter_node *block;
} pm_parameters_node_t;

/**
 * ParenthesesNode
 *
 * Represents a parenthesized expression
 *
 *     (10 + 34)
 *     ^^^^^^^^^
 *
 * Type: ::PM_PARENTHESES_NODE

 * Flags (#pm_parentheses_node_flags):
 * * ::PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS
 *
 * @extends pm_node_t
 */
typedef struct pm_parentheses_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ParenthesesNode#body
     */
    struct pm_node *body;

    /**
     * ParenthesesNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * ParenthesesNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_parentheses_node_t;

/**
 * PinnedExpressionNode
 *
 * Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
 *
 *     foo in ^(bar)
 *            ^^^^^^
 *
 * Type: ::PM_PINNED_EXPRESSION_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_pinned_expression_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * PinnedExpressionNode#expression
     *
     * The expression used in the pinned expression
     *
     *     foo in ^(bar)
     *              ^^^
     */
    struct pm_node *expression;

    /**
     * PinnedExpressionNode#operator_loc
     *
     * The location of the `^` operator
     *
     *     foo in ^(bar)
     *            ^
     */
    pm_location_t operator_loc;

    /**
     * PinnedExpressionNode#lparen_loc
     *
     * The location of the opening parenthesis.
     *
     *     foo in ^(bar)
     *             ^
     */
    pm_location_t lparen_loc;

    /**
     * PinnedExpressionNode#rparen_loc
     *
     * The location of the closing parenthesis.
     *
     *     foo in ^(bar)
     *                 ^
     */
    pm_location_t rparen_loc;
} pm_pinned_expression_node_t;

/**
 * PinnedVariableNode
 *
 * Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
 *
 *     foo in ^bar
 *            ^^^^
 *
 * Type: ::PM_PINNED_VARIABLE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_pinned_variable_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * PinnedVariableNode#variable
     *
     * The variable used in the pinned expression
     *
     *     foo in ^bar
     *             ^^^
     */
    struct pm_node *variable;

    /**
     * PinnedVariableNode#operator_loc
     *
     * The location of the `^` operator
     *
     *     foo in ^bar
     *            ^
     */
    pm_location_t operator_loc;
} pm_pinned_variable_node_t;

/**
 * PostExecutionNode
 *
 * Represents the use of the `END` keyword.
 *
 *     END { foo }
 *     ^^^^^^^^^^^
 *
 * Type: ::PM_POST_EXECUTION_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_post_execution_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * PostExecutionNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * PostExecutionNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * PostExecutionNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * PostExecutionNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_post_execution_node_t;

/**
 * PreExecutionNode
 *
 * Represents the use of the `BEGIN` keyword.
 *
 *     BEGIN { foo }
 *     ^^^^^^^^^^^^^
 *
 * Type: ::PM_PRE_EXECUTION_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_pre_execution_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * PreExecutionNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * PreExecutionNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * PreExecutionNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * PreExecutionNode#closing_loc
     */
    pm_location_t closing_loc;
} pm_pre_execution_node_t;

/**
 * ProgramNode
 *
 * The top level node of any parse tree.
 *
 * Type: ::PM_PROGRAM_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_program_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ProgramNode#locals
     */
    pm_constant_id_list_t locals;

    /**
     * ProgramNode#statements
     */
    struct pm_statements_node *statements;
} pm_program_node_t;

/**
 * RangeNode
 *
 * Represents the use of the `..` or `...` operators.
 *
 *     1..2
 *     ^^^^
 *
 *     c if a =~ /left/ ... b =~ /right/
 *          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_RANGE_NODE

 * Flags (#pm_range_flags):
 * * ::PM_RANGE_FLAGS_EXCLUDE_END
 *
 * @extends pm_node_t
 */
typedef struct pm_range_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RangeNode#left
     *
     * The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     1...
     *     ^
     *
     *     hello...goodbye
     *     ^^^^^
     */
    struct pm_node *left;

    /**
     * RangeNode#right
     *
     * The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     ..5
     *       ^
     *
     *     1...foo
     *         ^^^
     * If neither right-hand or left-hand side was included, this will be a MissingNode.
     */
    struct pm_node *right;

    /**
     * RangeNode#operator_loc
     *
     * The location of the `..` or `...` operator.
     */
    pm_location_t operator_loc;
} pm_range_node_t;

/**
 * RationalNode
 *
 * Represents a rational number literal.
 *
 *     1.0r
 *     ^^^^
 *
 * Type: ::PM_RATIONAL_NODE

 * Flags (#pm_integer_base_flags):
 * * ::PM_INTEGER_BASE_FLAGS_BINARY
 * * ::PM_INTEGER_BASE_FLAGS_DECIMAL
 * * ::PM_INTEGER_BASE_FLAGS_OCTAL
 * * ::PM_INTEGER_BASE_FLAGS_HEXADECIMAL
 *
 * @extends pm_node_t
 */
typedef struct pm_rational_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RationalNode#numerator
     *
     * The numerator of the rational number.
     *
     *     1.5r # numerator 3
     */
    pm_integer_t numerator;

    /**
     * RationalNode#denominator
     *
     * The denominator of the rational number.
     *
     *     1.5r # denominator 2
     */
    pm_integer_t denominator;
} pm_rational_node_t;

/**
 * RedoNode
 *
 * Represents the use of the `redo` keyword.
 *
 *     redo
 *     ^^^^
 *
 * Type: ::PM_REDO_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_redo_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_redo_node_t;

/**
 * RegularExpressionNode
 *
 * Represents a regular expression literal with no interpolation.
 *
 *     /foo/i
 *     ^^^^^^
 *
 * Type: ::PM_REGULAR_EXPRESSION_NODE

 * Flags (#pm_regular_expression_flags):
 * * ::PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EXTENDED
 * * ::PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ONCE
 * * ::PM_REGULAR_EXPRESSION_FLAGS_EUC_JP
 * * ::PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT
 * * ::PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J
 * * ::PM_REGULAR_EXPRESSION_FLAGS_UTF_8
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING
 *
 * @extends pm_node_t
 */
typedef struct pm_regular_expression_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RegularExpressionNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * RegularExpressionNode#content_loc
     */
    pm_location_t content_loc;

    /**
     * RegularExpressionNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * RegularExpressionNode#unescaped
     */
    pm_string_t unescaped;
} pm_regular_expression_node_t;

/**
 * RequiredKeywordParameterNode
 *
 * Represents a required keyword parameter to a method, block, or lambda definition.
 *
 *     def a(b: )
 *           ^^
 *     end
 *
 * Type: ::PM_REQUIRED_KEYWORD_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_required_keyword_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RequiredKeywordParameterNode#name
     */
    pm_constant_id_t name;

    /**
     * RequiredKeywordParameterNode#name_loc
     */
    pm_location_t name_loc;
} pm_required_keyword_parameter_node_t;

/**
 * RequiredParameterNode
 *
 * Represents a required parameter to a method, block, or lambda definition.
 *
 *     def a(b)
 *           ^
 *     end
 *
 * Type: ::PM_REQUIRED_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_required_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RequiredParameterNode#name
     */
    pm_constant_id_t name;
} pm_required_parameter_node_t;

/**
 * RescueModifierNode
 *
 * Represents an expression modified with a rescue.
 *
 *     foo rescue nil
 *     ^^^^^^^^^^^^^^
 *
 * Type: ::PM_RESCUE_MODIFIER_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_rescue_modifier_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RescueModifierNode#expression
     */
    struct pm_node *expression;

    /**
     * RescueModifierNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * RescueModifierNode#rescue_expression
     */
    struct pm_node *rescue_expression;
} pm_rescue_modifier_node_t;

/**
 * RescueNode
 *
 * Represents a rescue statement.
 *
 *     begin
 *     rescue Foo, *splat, Bar => ex
 *       foo
 *     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 *     end
 *
 * `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field.
 *
 * Type: ::PM_RESCUE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_rescue_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RescueNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * RescueNode#exceptions
     */
    struct pm_node_list exceptions;

    /**
     * RescueNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * RescueNode#reference
     */
    struct pm_node *reference;

    /**
     * RescueNode#then_keyword_loc
     */
    pm_location_t then_keyword_loc;

    /**
     * RescueNode#statements
     */
    struct pm_statements_node *statements;

    /**
     * RescueNode#subsequent
     */
    struct pm_rescue_node *subsequent;
} pm_rescue_node_t;

/**
 * RestParameterNode
 *
 * Represents a rest parameter to a method, block, or lambda definition.
 *
 *     def a(*b)
 *           ^^
 *     end
 *
 * Type: ::PM_REST_PARAMETER_NODE

 * Flags (#pm_parameter_flags):
 * * ::PM_PARAMETER_FLAGS_REPEATED_PARAMETER
 *
 * @extends pm_node_t
 */
typedef struct pm_rest_parameter_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * RestParameterNode#name
     */
    pm_constant_id_t name;

    /**
     * RestParameterNode#name_loc
     */
    pm_location_t name_loc;

    /**
     * RestParameterNode#operator_loc
     */
    pm_location_t operator_loc;
} pm_rest_parameter_node_t;

/**
 * RetryNode
 *
 * Represents the use of the `retry` keyword.
 *
 *     retry
 *     ^^^^^
 *
 * Type: ::PM_RETRY_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_retry_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_retry_node_t;

/**
 * ReturnNode
 *
 * Represents the use of the `return` keyword.
 *
 *     return 1
 *     ^^^^^^^^
 *
 * Type: ::PM_RETURN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_return_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ReturnNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * ReturnNode#arguments
     */
    struct pm_arguments_node *arguments;
} pm_return_node_t;

/**
 * SelfNode
 *
 * Represents the `self` keyword.
 *
 *     self
 *     ^^^^
 *
 * Type: ::PM_SELF_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_self_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_self_node_t;

/**
 * ShareableConstantNode
 *
 * This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified.
 *
 *     # shareable_constant_value: literal
 *     C = { a: 1 }
 *     ^^^^^^^^^^^^
 *
 * Type: ::PM_SHAREABLE_CONSTANT_NODE

 * Flags (#pm_shareable_constant_node_flags):
 * * ::PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL
 * * ::PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING
 * * ::PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY
 *
 * @extends pm_node_t
 */
typedef struct pm_shareable_constant_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * ShareableConstantNode#write
     *
     * The constant write that should be modified with the shareability state.
     */
    struct pm_node *write;
} pm_shareable_constant_node_t;

/**
 * SingletonClassNode
 *
 * Represents a singleton class declaration involving the `class` keyword.
 *
 *     class << self end
 *     ^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_SINGLETON_CLASS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_singleton_class_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * SingletonClassNode#locals
     */
    pm_constant_id_list_t locals;

    /**
     * SingletonClassNode#class_keyword_loc
     */
    pm_location_t class_keyword_loc;

    /**
     * SingletonClassNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * SingletonClassNode#expression
     */
    struct pm_node *expression;

    /**
     * SingletonClassNode#body
     */
    struct pm_node *body;

    /**
     * SingletonClassNode#end_keyword_loc
     */
    pm_location_t end_keyword_loc;
} pm_singleton_class_node_t;

/**
 * SourceEncodingNode
 *
 * Represents the use of the `__ENCODING__` keyword.
 *
 *     __ENCODING__
 *     ^^^^^^^^^^^^
 *
 * Type: ::PM_SOURCE_ENCODING_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_source_encoding_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_source_encoding_node_t;

/**
 * SourceFileNode
 *
 * Represents the use of the `__FILE__` keyword.
 *
 *     __FILE__
 *     ^^^^^^^^
 *
 * Type: ::PM_SOURCE_FILE_NODE

 * Flags (#pm_string_flags):
 * * ::PM_STRING_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_STRING_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_STRING_FLAGS_FROZEN
 * * ::PM_STRING_FLAGS_MUTABLE
 *
 * @extends pm_node_t
 */
typedef struct pm_source_file_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * SourceFileNode#filepath
     *
     * Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism::parse*` APIs.
     */
    pm_string_t filepath;
} pm_source_file_node_t;

/**
 * SourceLineNode
 *
 * Represents the use of the `__LINE__` keyword.
 *
 *     __LINE__
 *     ^^^^^^^^
 *
 * Type: ::PM_SOURCE_LINE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_source_line_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_source_line_node_t;

/**
 * SplatNode
 *
 * Represents the use of the splat operator.
 *
 *     [*a]
 *      ^^
 *
 * Type: ::PM_SPLAT_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_splat_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * SplatNode#operator_loc
     */
    pm_location_t operator_loc;

    /**
     * SplatNode#expression
     */
    struct pm_node *expression;
} pm_splat_node_t;

/**
 * StatementsNode
 *
 * Represents a set of statements contained within some scope.
 *
 *     foo; bar; baz
 *     ^^^^^^^^^^^^^
 *
 * Type: ::PM_STATEMENTS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_statements_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * StatementsNode#body
     */
    struct pm_node_list body;
} pm_statements_node_t;

/**
 * StringNode
 *
 * Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string.
 *
 *     "foo"
 *     ^^^^^
 *
 *     %w[foo]
 *        ^^^
 *
 *     "foo #{bar} baz"
 *      ^^^^      ^^^^
 *
 * Type: ::PM_STRING_NODE

 * Flags (#pm_string_flags):
 * * ::PM_STRING_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_STRING_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_STRING_FLAGS_FROZEN
 * * ::PM_STRING_FLAGS_MUTABLE
 *
 * @extends pm_node_t
 */
typedef struct pm_string_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * StringNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * StringNode#content_loc
     */
    pm_location_t content_loc;

    /**
     * StringNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * StringNode#unescaped
     */
    pm_string_t unescaped;
} pm_string_node_t;

/**
 * SuperNode
 *
 * Represents the use of the `super` keyword with parentheses or arguments.
 *
 *     super()
 *     ^^^^^^^
 *
 *     super foo, bar
 *     ^^^^^^^^^^^^^^
 *
 * If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead.
 *
 * Type: ::PM_SUPER_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_super_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * SuperNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * SuperNode#lparen_loc
     */
    pm_location_t lparen_loc;

    /**
     * SuperNode#arguments
     *
     * Can be only `nil` when there are empty parentheses, like `super()`.
     */
    struct pm_arguments_node *arguments;

    /**
     * SuperNode#rparen_loc
     */
    pm_location_t rparen_loc;

    /**
     * SuperNode#block
     */
    struct pm_node *block;
} pm_super_node_t;

/**
 * SymbolNode
 *
 * Represents a symbol literal or a symbol contained within a `%i` list.
 *
 *     :foo
 *     ^^^^
 *
 *     %i[foo]
 *        ^^^
 *
 * Type: ::PM_SYMBOL_NODE

 * Flags (#pm_symbol_flags):
 * * ::PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING
 * * ::PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING
 *
 * @extends pm_node_t
 */
typedef struct pm_symbol_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * SymbolNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * SymbolNode#value_loc
     */
    pm_location_t value_loc;

    /**
     * SymbolNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * SymbolNode#unescaped
     */
    pm_string_t unescaped;
} pm_symbol_node_t;

/**
 * TrueNode
 *
 * Represents the use of the literal `true` keyword.
 *
 *     true
 *     ^^^^
 *
 * Type: ::PM_TRUE_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_true_node {
    /** The embedded base node. */
    pm_node_t base;

} pm_true_node_t;

/**
 * UndefNode
 *
 * Represents the use of the `undef` keyword.
 *
 *     undef :foo, :bar, :baz
 *     ^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_UNDEF_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_undef_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * UndefNode#names
     */
    struct pm_node_list names;

    /**
     * UndefNode#keyword_loc
     */
    pm_location_t keyword_loc;
} pm_undef_node_t;

/**
 * UnlessNode
 *
 * Represents the use of the `unless` keyword, either in the block form or the modifier form.
 *
 *     bar unless foo
 *     ^^^^^^^^^^^^^^
 *
 *     unless foo then bar end
 *     ^^^^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_UNLESS_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_unless_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * UnlessNode#keyword_loc
     *
     * The location of the `unless` keyword.
     *
     *     unless cond then bar end
     *     ^^^^^^
     *
     *     bar unless cond
     *         ^^^^^^
     */
    pm_location_t keyword_loc;

    /**
     * UnlessNode#predicate
     *
     * The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
     *
     *     unless cond then bar end
     *            ^^^^
     *
     *     bar unless cond
     *                ^^^^
     */
    struct pm_node *predicate;

    /**
     * UnlessNode#then_keyword_loc
     *
     * The location of the `then` keyword, if present.
     *
     *     unless cond then bar end
     *                 ^^^^
     */
    pm_location_t then_keyword_loc;

    /**
     * UnlessNode#statements
     *
     * The body of statements that will executed if the unless condition is
     * falsey. Will be `nil` if no body is provided.
     *
     *     unless cond then bar end
     *                      ^^^
     */
    struct pm_statements_node *statements;

    /**
     * UnlessNode#else_clause
     *
     * The else clause of the unless expression, if present.
     *
     *     unless cond then bar else baz end
     *                          ^^^^^^^^
     */
    struct pm_else_node *else_clause;

    /**
     * UnlessNode#end_keyword_loc
     *
     * The location of the `end` keyword, if present.
     *
     *     unless cond then bar end
     *                          ^^^
     */
    pm_location_t end_keyword_loc;
} pm_unless_node_t;

/**
 * UntilNode
 *
 * Represents the use of the `until` keyword, either in the block form or the modifier form.
 *
 *     bar until foo
 *     ^^^^^^^^^^^^^
 *
 *     until foo do bar end
 *     ^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_UNTIL_NODE

 * Flags (#pm_loop_flags):
 * * ::PM_LOOP_FLAGS_BEGIN_MODIFIER
 *
 * @extends pm_node_t
 */
typedef struct pm_until_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * UntilNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * UntilNode#do_keyword_loc
     */
    pm_location_t do_keyword_loc;

    /**
     * UntilNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * UntilNode#predicate
     */
    struct pm_node *predicate;

    /**
     * UntilNode#statements
     */
    struct pm_statements_node *statements;
} pm_until_node_t;

/**
 * WhenNode
 *
 * Represents the use of the `when` keyword within a case statement.
 *
 *     case true
 *     when true
 *     ^^^^^^^^^
 *     end
 *
 * Type: ::PM_WHEN_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_when_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * WhenNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * WhenNode#conditions
     */
    struct pm_node_list conditions;

    /**
     * WhenNode#then_keyword_loc
     */
    pm_location_t then_keyword_loc;

    /**
     * WhenNode#statements
     */
    struct pm_statements_node *statements;
} pm_when_node_t;

/**
 * WhileNode
 *
 * Represents the use of the `while` keyword, either in the block form or the modifier form.
 *
 *     bar while foo
 *     ^^^^^^^^^^^^^
 *
 *     while foo do bar end
 *     ^^^^^^^^^^^^^^^^^^^^
 *
 * Type: ::PM_WHILE_NODE

 * Flags (#pm_loop_flags):
 * * ::PM_LOOP_FLAGS_BEGIN_MODIFIER
 *
 * @extends pm_node_t
 */
typedef struct pm_while_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * WhileNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * WhileNode#do_keyword_loc
     */
    pm_location_t do_keyword_loc;

    /**
     * WhileNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * WhileNode#predicate
     */
    struct pm_node *predicate;

    /**
     * WhileNode#statements
     */
    struct pm_statements_node *statements;
} pm_while_node_t;

/**
 * XStringNode
 *
 * Represents an xstring literal with no interpolation.
 *
 *     `foo`
 *     ^^^^^
 *
 * Type: ::PM_X_STRING_NODE

 * Flags (#pm_encoding_flags):
 * * ::PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING
 * * ::PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING
 *
 * @extends pm_node_t
 */
typedef struct pm_x_string_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * XStringNode#opening_loc
     */
    pm_location_t opening_loc;

    /**
     * XStringNode#content_loc
     */
    pm_location_t content_loc;

    /**
     * XStringNode#closing_loc
     */
    pm_location_t closing_loc;

    /**
     * XStringNode#unescaped
     */
    pm_string_t unescaped;
} pm_x_string_node_t;

/**
 * YieldNode
 *
 * Represents the use of the `yield` keyword.
 *
 *     yield 1
 *     ^^^^^^^
 *
 * Type: ::PM_YIELD_NODE
 *
 * @extends pm_node_t
 */
typedef struct pm_yield_node {
    /** The embedded base node. */
    pm_node_t base;


    /**
     * YieldNode#keyword_loc
     */
    pm_location_t keyword_loc;

    /**
     * YieldNode#lparen_loc
     */
    pm_location_t lparen_loc;

    /**
     * YieldNode#arguments
     */
    struct pm_arguments_node *arguments;

    /**
     * YieldNode#rparen_loc
     */
    pm_location_t rparen_loc;
} pm_yield_node_t;

/**
 * Flags for arguments nodes.
 */
typedef enum pm_arguments_node_flags {
    /** if the arguments contain forwarding */
    PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING = 4,

    /** if the arguments contain keywords */
    PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS = 8,

    /** if the arguments contain a keyword splat */
    PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT = 16,

    /** if the arguments contain a splat */
    PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT = 32,

    /** if the arguments contain multiple splats */
    PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS = 64,

    PM_ARGUMENTS_NODE_FLAGS_LAST,
} pm_arguments_node_flags_t;

/**
 * Flags for array nodes.
 */
typedef enum pm_array_node_flags {
    /** if array contains splat nodes */
    PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT = 4,

    PM_ARRAY_NODE_FLAGS_LAST,
} pm_array_node_flags_t;

/**
 * Flags for call nodes.
 */
typedef enum pm_call_node_flags {
    /** &. operator */
    PM_CALL_NODE_FLAGS_SAFE_NAVIGATION = 4,

    /** a call that could have been a local variable */
    PM_CALL_NODE_FLAGS_VARIABLE_CALL = 8,

    /** a call that is an attribute write, so the value being written should be returned */
    PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE = 16,

    /** a call that ignores method visibility */
    PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY = 32,

    PM_CALL_NODE_FLAGS_LAST,
} pm_call_node_flags_t;

/**
 * Flags for nodes that have unescaped content.
 */
typedef enum pm_encoding_flags {
    /** internal bytes forced the encoding to UTF-8 */
    PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING = 4,

    /** internal bytes forced the encoding to binary */
    PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING = 8,

    PM_ENCODING_FLAGS_LAST,
} pm_encoding_flags_t;

/**
 * Flags for integer nodes that correspond to the base of the integer.
 */
typedef enum pm_integer_base_flags {
    /** 0b prefix */
    PM_INTEGER_BASE_FLAGS_BINARY = 4,

    /** 0d or no prefix */
    PM_INTEGER_BASE_FLAGS_DECIMAL = 8,

    /** 0o or 0 prefix */
    PM_INTEGER_BASE_FLAGS_OCTAL = 16,

    /** 0x prefix */
    PM_INTEGER_BASE_FLAGS_HEXADECIMAL = 32,

    PM_INTEGER_BASE_FLAGS_LAST,
} pm_integer_base_flags_t;

/**
 * Flags for interpolated string nodes that indicated mutability if they are also marked as literals.
 */
typedef enum pm_interpolated_string_node_flags {
    /** frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` */
    PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN = 4,

    /** mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` */
    PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE = 8,

    PM_INTERPOLATED_STRING_NODE_FLAGS_LAST,
} pm_interpolated_string_node_flags_t;

/**
 * Flags for keyword hash nodes.
 */
typedef enum pm_keyword_hash_node_flags {
    /** a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments */
    PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS = 4,

    PM_KEYWORD_HASH_NODE_FLAGS_LAST,
} pm_keyword_hash_node_flags_t;

/**
 * Flags for while and until loop nodes.
 */
typedef enum pm_loop_flags {
    /** a loop after a begin statement, so the body is executed first before the condition */
    PM_LOOP_FLAGS_BEGIN_MODIFIER = 4,

    PM_LOOP_FLAGS_LAST,
} pm_loop_flags_t;

/**
 * Flags for parameter nodes.
 */
typedef enum pm_parameter_flags {
    /** a parameter name that has been repeated in the method signature */
    PM_PARAMETER_FLAGS_REPEATED_PARAMETER = 4,

    PM_PARAMETER_FLAGS_LAST,
} pm_parameter_flags_t;

/**
 * Flags for parentheses nodes.
 */
typedef enum pm_parentheses_node_flags {
    /** parentheses that contain multiple potentially void statements */
    PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS = 4,

    PM_PARENTHESES_NODE_FLAGS_LAST,
} pm_parentheses_node_flags_t;

/**
 * Flags for range and flip-flop nodes.
 */
typedef enum pm_range_flags {
    /** ... operator */
    PM_RANGE_FLAGS_EXCLUDE_END = 4,

    PM_RANGE_FLAGS_LAST,
} pm_range_flags_t;

/**
 * Flags for regular expression and match last line nodes.
 */
typedef enum pm_regular_expression_flags {
    /** i - ignores the case of characters when matching */
    PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE = 4,

    /** x - ignores whitespace and allows comments in regular expressions */
    PM_REGULAR_EXPRESSION_FLAGS_EXTENDED = 8,

    /** m - allows $ to match the end of lines within strings */
    PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE = 16,

    /** o - only interpolates values into the regular expression once */
    PM_REGULAR_EXPRESSION_FLAGS_ONCE = 32,

    /** e - forces the EUC-JP encoding */
    PM_REGULAR_EXPRESSION_FLAGS_EUC_JP = 64,

    /** n - forces the ASCII-8BIT encoding */
    PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT = 128,

    /** s - forces the Windows-31J encoding */
    PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J = 256,

    /** u - forces the UTF-8 encoding */
    PM_REGULAR_EXPRESSION_FLAGS_UTF_8 = 512,

    /** internal bytes forced the encoding to UTF-8 */
    PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING = 1024,

    /** internal bytes forced the encoding to binary */
    PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING = 2048,

    /** internal bytes forced the encoding to US-ASCII */
    PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING = 4096,

    PM_REGULAR_EXPRESSION_FLAGS_LAST,
} pm_regular_expression_flags_t;

/**
 * Flags for shareable constant nodes.
 */
typedef enum pm_shareable_constant_node_flags {
    /** constant writes that should be modified with shareable constant value literal */
    PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL = 4,

    /** constant writes that should be modified with shareable constant value experimental everything */
    PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING = 8,

    /** constant writes that should be modified with shareable constant value experimental copy */
    PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY = 16,

    PM_SHAREABLE_CONSTANT_NODE_FLAGS_LAST,
} pm_shareable_constant_node_flags_t;

/**
 * Flags for string nodes.
 */
typedef enum pm_string_flags {
    /** internal bytes forced the encoding to UTF-8 */
    PM_STRING_FLAGS_FORCED_UTF8_ENCODING = 4,

    /** internal bytes forced the encoding to binary */
    PM_STRING_FLAGS_FORCED_BINARY_ENCODING = 8,

    /** frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` */
    PM_STRING_FLAGS_FROZEN = 16,

    /** mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` */
    PM_STRING_FLAGS_MUTABLE = 32,

    PM_STRING_FLAGS_LAST,
} pm_string_flags_t;

/**
 * Flags for symbol nodes.
 */
typedef enum pm_symbol_flags {
    /** internal bytes forced the encoding to UTF-8 */
    PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING = 4,

    /** internal bytes forced the encoding to binary */
    PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING = 8,

    /** internal bytes forced the encoding to US-ASCII */
    PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING = 16,

    PM_SYMBOL_FLAGS_LAST,
} pm_symbol_flags_t;

/**
 * When we're serializing to Java, we want to skip serializing the location
 * fields as they won't be used by JRuby or TruffleRuby. This boolean allows us
 * to specify that through the environment. It will never be true except for in
 * those build systems.
 */
#define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS 0

#endif
