Skip to content

Commit 687df83

Browse files
committed
refactoring
1 parent 4e3f3be commit 687df83

File tree

4 files changed

+56
-61
lines changed

4 files changed

+56
-61
lines changed

jcp/src/main/java/com/igormaznitsa/jcp/expression/Expression.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ private ExpressionTreeElement evalFunction(
9898
final AbstractFunction functionElement = (AbstractFunction) treeElement.getItem();
9999
final List<ExpressionTreeElement> children = treeElement.extractEffectiveChildren();
100100

101-
if (!functionElement.getArity().contains(children.size())) {
101+
if (!functionElement.getArity().contains(-1) &&
102+
!functionElement.getArity().contains(children.size())) {
102103
throw context
103104
.makeException(
104105
"Can't find '" + functionElement.getName() + "' for arity " + children.size(), null);

jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionParser.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
package com.igormaznitsa.jcp.expression;
2323

24+
import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY;
2425
import static java.util.Objects.requireNonNull;
2526
import static java.util.Objects.requireNonNullElseGet;
2627

@@ -38,6 +39,7 @@
3839
import java.util.ArrayList;
3940
import java.util.List;
4041
import java.util.Locale;
42+
import java.util.Set;
4143
import java.util.stream.Collectors;
4244

4345
/**
@@ -260,7 +262,8 @@ private ExpressionTree readFunction(
260262
functionTree.addItem(function);
261263
ExpressionTreeElement functionTreeElement = functionTree.getRoot();
262264

263-
if (!functionTreeElement.getAllowedArities().contains(arguments.size())) {
265+
final Set<Integer> expectedArities = functionTreeElement.getExpectedArities();
266+
if (!expectedArities.contains(ANY_ARITY) && !expectedArities.contains(arguments.size())) {
264267
throw context.makeException(
265268
"Wrong argument number detected for '" + function.getName() + "', expected " +
266269
function.getArity().stream().map(Object::toString)

jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionTreeElement.java

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
package com.igormaznitsa.jcp.expression;
2323

24+
import static com.igormaznitsa.jcp.expression.functions.AbstractFunction.ARITY_0;
25+
2426
import com.igormaznitsa.jcp.exceptions.FilePositionInfo;
2527
import com.igormaznitsa.jcp.exceptions.PreprocessorException;
2628
import com.igormaznitsa.jcp.expression.functions.AbstractFunction;
@@ -40,6 +42,7 @@
4042
public class ExpressionTreeElement {
4143

4244
public static final ExpressionTreeElement EMPTY_SLOT = new ExpressionTreeElement();
45+
4346
/**
4447
* Inside constant to be used for speed up some operations
4548
*/
@@ -48,6 +51,8 @@ public class ExpressionTreeElement {
4851
* Empty array to avoid unnecessary operations
4952
*/
5053
private static final ExpressionTreeElement[] EMPTY = new ExpressionTreeElement[0];
54+
public static final int ANY_ARITY = -1;
55+
private static final int MAX_FUNCTION_ARGUMENTS = 256;
5156
/**
5257
* Contains the source string for the expression.
5358
*/
@@ -63,7 +68,7 @@ public class ExpressionTreeElement {
6368
/**
6469
* The array contains links to the tree element children
6570
*/
66-
private ExpressionTreeElement[] childElements;
71+
private ExpressionTreeElement[] childrenSlots;
6772
/**
6873
* The link to the parent element, if it is the tree root then it contains null
6974
*/
@@ -75,21 +80,18 @@ public class ExpressionTreeElement {
7580
/**
7681
* Because I fill children sequentially, the variable contains the index of the first empty child slot
7782
*/
78-
private int nextChildSlot = 0;
79-
80-
private static final Set<Integer> ZERO_ARITY = Set.of(0);
81-
82-
private ExpressionTreeElement() {
83-
this.sourceString = "";
84-
this.includeStack = new FilePositionInfo[0];
85-
}
83+
private int nextChildSlotIndex = 0;
8684
/**
8785
* Set of allowed arities.
8886
*
8987
* @since 7.3.0
9088
*/
91-
private Set<Integer> allowedArities = Set.of();
89+
private Set<Integer> expectedArities = Set.of();
9290

91+
private ExpressionTreeElement() {
92+
this.sourceString = "";
93+
this.includeStack = new FilePositionInfo[0];
94+
}
9395
/**
9496
* The constructor
9597
*
@@ -107,22 +109,23 @@ private ExpressionTreeElement() {
107109
this.includeStack, null);
108110
}
109111

110-
final int arity;
111112
if (item.getExpressionItemType() == ExpressionItemType.OPERATOR) {
112-
arity = ((AbstractOperator) item).getArity();
113-
this.allowedArities = Set.of(arity);
113+
final int arity = ((AbstractOperator) item).getArity();
114+
this.expectedArities = Set.of(arity);
115+
this.childrenSlots = new ExpressionTreeElement[arity];
114116
} else if (item.getExpressionItemType() == ExpressionItemType.FUNCTION) {
115117
final AbstractFunction functionItem = (AbstractFunction) item;
116-
this.allowedArities = functionItem.getArity();
117-
arity = this.allowedArities.stream().mapToInt(x -> x).max().orElse(0);
118+
this.expectedArities = functionItem.getArity();
119+
final int arity = this.expectedArities.stream().mapToInt(x -> x).max().orElse(0);
120+
this.childrenSlots = this.expectedArities.contains(ANY_ARITY) ?
121+
new ExpressionTreeElement[MAX_FUNCTION_ARGUMENTS] : new ExpressionTreeElement[arity];
118122
} else {
119-
arity = 0;
120-
this.allowedArities = ZERO_ARITY;
123+
this.expectedArities = ARITY_0;
124+
this.childrenSlots = EMPTY;
121125
}
122-
priority = item.getExpressionItemPriority().getPriority();
126+
this.priority = item.getExpressionItemPriority().getPriority();
123127
this.savedItem = item;
124-
childElements = arity == 0 ? EMPTY : new ExpressionTreeElement[arity];
125-
Arrays.fill(this.childElements, EMPTY_SLOT);
128+
Arrays.fill(this.childrenSlots, EMPTY_SLOT);
126129
}
127130

128131
/**
@@ -132,18 +135,18 @@ private ExpressionTreeElement() {
132135
* @since 7.3.0
133136
*/
134137
public List<ExpressionTreeElement> extractEffectiveChildren() {
135-
return Arrays.stream(this.childElements).takeWhile(x -> x != EMPTY_SLOT)
138+
return Arrays.stream(this.childrenSlots).takeWhile(x -> x != EMPTY_SLOT)
136139
.collect(Collectors.toUnmodifiableList());
137140
}
138141

139142
/**
140143
* Variants of allowed arities by the expression tree element
141144
*
142-
* @return allowed artiy numbers as set
145+
* @return set contains number of expected arities
143146
* @since 7.3.0
144147
*/
145-
public Set<Integer> getAllowedArities() {
146-
return this.allowedArities;
148+
public Set<Integer> getExpectedArities() {
149+
return this.expectedArities;
147150
}
148151

149152
/**
@@ -178,15 +181,6 @@ public ExpressionItem getItem() {
178181
return this.savedItem;
179182
}
180183

181-
/**
182-
* Get arity for the element (I mean possible children number)
183-
*
184-
* @return the arity, zero for elements without children
185-
*/
186-
public int getArity() {
187-
return childElements.length;
188-
}
189-
190184
/**
191185
* Get the parent for the element
192186
*
@@ -247,7 +241,7 @@ public boolean replaceElement(final ExpressionTreeElement oldOne,
247241

248242
boolean result = false;
249243

250-
final ExpressionTreeElement[] children = childElements;
244+
final ExpressionTreeElement[] children = childrenSlots;
251245
final int len = children.length;
252246

253247
for (int i = 0; i < len; i++) {
@@ -272,7 +266,7 @@ public boolean replaceElement(final ExpressionTreeElement oldOne,
272266

273267
public ExpressionTreeElement getChildForIndex(final int index) {
274268
assertNotEmptySlot();
275-
return this.childElements[index];
269+
return this.childrenSlots[index];
276270
}
277271

278272
/**
@@ -287,11 +281,8 @@ public ExpressionTreeElement addTreeElement(final ExpressionTreeElement element)
287281
Objects.requireNonNull(element, "The element is null");
288282

289283
final int newElementPriority = element.getPriority();
290-
291284
ExpressionTreeElement result = this;
292-
293285
final ExpressionTreeElement parentTreeElement = this.parentTreeElement;
294-
295286
final int currentPriority = getPriority();
296287

297288
if (newElementPriority < currentPriority) {
@@ -305,22 +296,21 @@ public ExpressionTreeElement addTreeElement(final ExpressionTreeElement element)
305296
if (parentTreeElement != null) {
306297
parentTreeElement.replaceElement(this, element);
307298
}
308-
if (element.nextChildSlot >= element.childElements.length) {
299+
if (element.nextChildSlotIndex >= element.childrenSlots.length) {
309300
throw new PreprocessorException(
310301
"[Expression]Can't process expression item, may be wrong number of arguments",
311302
this.sourceString, this.includeStack, null);
312303
}
313-
element.childElements[element.nextChildSlot] = this;
314-
element.nextChildSlot++;
304+
element.childrenSlots[element.nextChildSlotIndex] = this;
305+
element.nextChildSlotIndex++;
315306
this.parentTreeElement = element;
316307
result = element;
317-
} else if (isFull()) {
318-
final int lastElementIndex = getArity() - 1;
319-
320-
final ExpressionTreeElement lastElement = childElements[lastElementIndex];
308+
} else if (this.isFull()) {
309+
final int lastElementIndex = this.nextChildSlotIndex - 1;
310+
final ExpressionTreeElement lastElement = this.childrenSlots[lastElementIndex];
321311
if (lastElement.getPriority() > newElementPriority) {
322312
element.addElementToNextFreeSlot(lastElement);
323-
childElements[lastElementIndex] = element;
313+
this.childrenSlots[lastElementIndex] = element;
324314
element.parentTreeElement = this;
325315
result = element;
326316
}
@@ -338,7 +328,7 @@ public ExpressionTreeElement addTreeElement(final ExpressionTreeElement element)
338328
* @return true if there is not any free child slot else false
339329
*/
340330
public boolean isFull() {
341-
return nextChildSlot >= childElements.length;
331+
return this.nextChildSlotIndex >= this.childrenSlots.length;
342332
}
343333

344334
/**
@@ -354,7 +344,7 @@ public void fillArguments(final List<ExpressionTree> arguments) {
354344
this.includeStack, null);
355345
}
356346

357-
if (childElements.length != arguments.size()) {
347+
if (childrenSlots.length != arguments.size()) {
358348
throw new PreprocessorException("Wrong argument list size", this.sourceString,
359349
this.includeStack, null);
360350
}
@@ -366,7 +356,7 @@ public void fillArguments(final List<ExpressionTree> arguments) {
366356
this.sourceString, this.includeStack, null);
367357
}
368358

369-
if (!childElements[i].isEmptySlot()) {
359+
if (!childrenSlots[i].isEmptySlot()) {
370360
throw new PreprocessorException(
371361
"[Expression]Non-empty slot detected, it is possible that there is a program error, contact a developer please",
372362
this.sourceString, this.includeStack, null);
@@ -377,7 +367,7 @@ public void fillArguments(final List<ExpressionTree> arguments) {
377367
throw new PreprocessorException("[Expression]Empty argument [" + (i + 1) + "] detected",
378368
this.sourceString, this.includeStack, null);
379369
}
380-
childElements[i] = root;
370+
childrenSlots[i] = root;
381371
root.parentTreeElement = this;
382372

383373
i++;
@@ -395,7 +385,7 @@ private void addElementToNextFreeSlot(final ExpressionTreeElement element) {
395385
this.includeStack, null);
396386
}
397387

398-
if (childElements.length == 0) {
388+
if (childrenSlots.length == 0) {
399389
throw new PreprocessorException(
400390
"[Expression]Unexpected element, may be unknown function [" + savedItem.toString() + ']',
401391
this.sourceString, this.includeStack, null);
@@ -404,7 +394,7 @@ private void addElementToNextFreeSlot(final ExpressionTreeElement element) {
404394
"[Expression]There is not any possibility to add new argument [" + savedItem.toString() +
405395
']', this.sourceString, this.includeStack, null);
406396
} else {
407-
childElements[nextChildSlot++] = element;
397+
childrenSlots[nextChildSlotIndex++] = element;
408398
}
409399
element.parentTreeElement = this;
410400
}
@@ -418,20 +408,20 @@ public void postProcess() {
418408
switch (savedItem.getExpressionItemType()) {
419409
case OPERATOR: {
420410
if (savedItem == OPERATOR_SUB) {
421-
if (!childElements[0].isEmptySlot() && childElements[1].isEmptySlot()) {
422-
final ExpressionTreeElement left = childElements[0];
411+
if (!childrenSlots[0].isEmptySlot() && childrenSlots[1].isEmptySlot()) {
412+
final ExpressionTreeElement left = childrenSlots[0];
423413
final ExpressionItem item = left.getItem();
424414
if (item.getExpressionItemType() == ExpressionItemType.VALUE) {
425415
final Value val = (Value) item;
426416
switch (val.getType()) {
427417
case INT: {
428-
childElements = EMPTY;
418+
childrenSlots = EMPTY;
429419
savedItem = Value.valueOf(-val.asLong());
430420
makeMaxPriority();
431421
}
432422
break;
433423
case FLOAT: {
434-
childElements = EMPTY;
424+
childrenSlots = EMPTY;
435425
savedItem = Value.valueOf(0.0f - val.asFloat());
436426
makeMaxPriority();
437427
}
@@ -445,14 +435,14 @@ public void postProcess() {
445435
}
446436
}
447437
} else {
448-
for (final ExpressionTreeElement element : childElements) {
438+
for (final ExpressionTreeElement element : childrenSlots) {
449439
if (!element.isEmptySlot()) {
450440
element.postProcess();
451441
}
452442
}
453443
}
454444
} else {
455-
for (final ExpressionTreeElement element : childElements) {
445+
for (final ExpressionTreeElement element : childrenSlots) {
456446
if (!element.isEmptySlot()) {
457447
element.postProcess();
458448
}
@@ -461,7 +451,7 @@ public void postProcess() {
461451
}
462452
break;
463453
case FUNCTION: {
464-
for (final ExpressionTreeElement element : childElements) {
454+
for (final ExpressionTreeElement element : childrenSlots) {
465455
if (!element.isEmptySlot()) {
466456
element.postProcess();
467457
}

jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/AbstractFunction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
*/
5151
public abstract class AbstractFunction implements ExpressionItem {
5252

53+
public static final Set<Integer> ARITY_ANY = Set.of(-1);
5354
public static final Set<Integer> ARITY_0 = Set.of(0);
5455
public static final Set<Integer> ARITY_1 = Set.of(1);
5556
public static final Set<Integer> ARITY_1_2 = Set.of(1, 2);

0 commit comments

Comments
 (0)