-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathListNode.java
More file actions
183 lines (170 loc) · 6.7 KB
/
ListNode.java
File metadata and controls
183 lines (170 loc) · 6.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package org.perlonjava.astnode;
import org.perlonjava.astvisitor.Visitor;
import org.perlonjava.astrefactor.LargeNodeRefactorer;
import org.perlonjava.parser.Parser;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a list expression in the AST, corresponding to Perl's {@code (...)} syntax.
* <p>
* ListNode is used for:
* <ul>
* <li>Parenthesized lists: {@code (1, 2, 3)}</li>
* <li>Function arguments: {@code foo($a, $b, $c)}</li>
* <li>Assignment targets: {@code ($x, $y) = @array}</li>
* <li>qw// lists: {@code qw(a b c)}</li>
* </ul>
* <p>
* Unlike {@link ArrayLiteralNode} which creates an array reference, ListNode represents
* a flat list that can be assigned to arrays or used in list context.
* <p>
* <b>Large Literal Handling:</b> The constructor automatically invokes
* {@link LargeNodeRefactorer#maybeRefactorElements} to split very large lists
* into chunks (currently disabled - on-demand refactoring is used instead).
*
* @see LargeNodeRefactorer
* @see ArrayLiteralNode
* @see HashLiteralNode
*/
public class ListNode extends AbstractNode {
/**
* The list of element nodes contained in this list expression.
* <p>
* Each element is an AST node representing an expression. Elements are evaluated
* in the context determined by how the list is used (list context for assignments,
* scalar context for the last element in scalar context, etc.).
* <p>
* Note: This field is non-final because {@link LargeNodeRefactorer} may replace
* the original list with a refactored version containing chunk wrappers.
*/
public List<Node> elements;
/**
* Optional handle node for I/O operations or block for list transformations.
* <p>
* This field is used in several contexts:
* <ul>
* <li>{@code print HANDLE @list} - HANDLE is stored here</li>
* <li>{@code say HANDLE @list} - HANDLE is stored here</li>
* <li>{@code map BLOCK @list} - BLOCK is stored here</li>
* <li>{@code grep BLOCK @list} - BLOCK is stored here</li>
* <li>{@code sort BLOCK @list} - BLOCK is stored here</li>
* </ul>
*/
public Node handle;
/**
* Constructs a ListNode with the specified elements.
* <p>
* <b>Large Literal Refactoring:</b> Currently disabled by default.
* Large code is handled automatically via on-demand refactoring when compilation errors occur.
*
* @param elements the list of child nodes to be stored in this ListNode
* @param tokenIndex the token index in the source for error reporting
* @see LargeNodeRefactorer#maybeRefactorElements
*/
public ListNode(List<Node> elements, int tokenIndex) {
this(elements, tokenIndex, null);
}
/**
* Constructs a ListNode with the specified elements and parser context.
* <p>
* This constructor provides better error messages with source code context when refactoring fails.
*
* @param elements the list of child nodes to be stored in this ListNode
* @param tokenIndex the token index in the source for error reporting
* @param parser the parser instance for access to error utilities
* @see LargeNodeRefactorer#maybeRefactorElements
*/
public ListNode(List<Node> elements, int tokenIndex, Parser parser) {
this.tokenIndex = tokenIndex;
this.elements = LargeNodeRefactorer.maybeRefactorElements(elements, tokenIndex, parser);
this.handle = null;
}
/**
* Constructs an empty ListNode.
* <p>
* This constructor creates a list with no elements, useful for building
* lists incrementally or representing empty argument lists.
*
* @param tokenIndex the token index in the source for error reporting
*/
public ListNode(int tokenIndex) {
this.elements = new ArrayList<>();
this.tokenIndex = tokenIndex;
this.handle = null;
}
/**
* Creates a ListNode from a single node, or returns the node if it's already a ListNode.
* <p>
* This is a convenience method for normalizing nodes to list form.
*
* @param left the node to wrap in a list (or return as-is if already a ListNode)
* @return a ListNode containing the input node
*/
public static ListNode makeList(Node left) {
if (left instanceof ListNode) {
return (ListNode) left;
}
List<Node> list = new ArrayList<>();
list.add(left);
return new ListNode(list, left.getIndex());
}
/**
* Creates a ListNode by concatenating two nodes.
* <p>
* Both nodes are first converted to ListNodes (if not already), then their
* elements are combined into a single list.
*
* @param left the first node (or list of nodes)
* @param right the second node (or list of nodes)
* @return a ListNode containing all elements from both inputs
*/
public static ListNode makeList(Node left, Node right) {
ListNode leftList = ListNode.makeList(left);
ListNode rightList = ListNode.makeList(right);
int size = rightList.elements.size();
for (int i = 0; i < size; i++) {
leftList.elements.add(rightList.elements.get(i));
}
return leftList;
}
/**
* Creates a ListNode by concatenating two nodes and appending a third.
*
* @param left the first node (or list of nodes)
* @param right the second node (or list of nodes)
* @param more an additional node to append
* @return a ListNode containing all elements
*/
public static ListNode makeList(Node left, Node right, Node more) {
ListNode leftList = ListNode.makeList(left, right);
leftList.elements.add(more);
return leftList;
}
/**
* Creates a ListNode by concatenating two nodes and appending two more.
*
* @param left the first node (or list of nodes)
* @param right the second node (or list of nodes)
* @param more an additional node to append
* @param more2 another additional node to append
* @return a ListNode containing all elements
*/
public static ListNode makeList(Node left, Node right, Node more, Node more2) {
ListNode leftList = ListNode.makeList(left, right);
leftList.elements.add(more);
leftList.elements.add(more2);
return leftList;
}
/**
* Accepts a visitor that performs some operation on this node.
* This method is part of the Visitor design pattern, which allows
* for defining new operations on the AST nodes without changing
* the node classes.
*
* @param visitor the visitor that will perform the operation on this node
*/
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}