Skip to content

Commit bd047d1

Browse files
committed
refactoring
1 parent 6f9c8a0 commit bd047d1

File tree

6 files changed

+128
-49
lines changed

6 files changed

+128
-49
lines changed

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
package com.igormaznitsa.jcp.expression;
2323

2424
import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY;
25+
import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.MAX_FUNCTION_ARGUMENTS;
2526
import static java.util.Objects.requireNonNull;
2627
import static java.util.Objects.requireNonNullElseGet;
2728

@@ -111,7 +112,7 @@ public ExpressionTree parse(final String expressionStr, final PreprocessorContex
111112
final PreprocessingState state = context.getPreprocessingState();
112113
result = new ExpressionTree(state.makeIncludeStack(), state.getLastReadString());
113114

114-
if (readExpression(reader, result, context, false, false) != null) {
115+
if (this.readExpression(reader, result, context, false, false) != null) {
115116
final String text = "Unexpected result during parsing [" + expressionStr + ']';
116117
throw context.makeException(text, null);
117118
}
@@ -187,8 +188,7 @@ public ExpressionItem readExpression(
187188
}
188189
} else if (nextItem.getExpressionItemType() == ExpressionItemType.FUNCTION) {
189190
final AbstractFunction function = (AbstractFunction) nextItem;
190-
ExpressionTree functionTree = readFunction(function, reader, context, stack, sourceLine);
191-
tree.addTree(functionTree);
191+
tree.addTree(this.readFunction(function, reader, context, stack, sourceLine));
192192
} else {
193193
tree.addItem(nextItem);
194194
}
@@ -221,7 +221,9 @@ private ExpressionTree readFunction(
221221
.makeException("Detected function without params [" + function.getName() + ']', null);
222222
}
223223

224-
final int maxArity = function.getArity().stream().mapToInt(x -> x).max().orElse(0);
224+
final Set<Integer> arities = function.getArity();
225+
final int maxArity = arities.contains(ANY_ARITY) ? MAX_FUNCTION_ARGUMENTS :
226+
arities.stream().mapToInt(x -> x).max().orElse(0);
225227

226228
ExpressionTree functionTree;
227229
if (maxArity == 0) {
@@ -617,8 +619,14 @@ ExpressionItem nextItem(final PushbackReader reader, final PreprocessorContext c
617619
"Can't find any preprocessor extension processing the user functions [" +
618620
userFunctionName + ']', null);
619621
} else {
620-
result = new FunctionDefinedByUser(userFunctionName,
621-
preprocessorExtension.getUserFunctionArity(userFunctionName), context);
622+
final Set<Integer> arities =
623+
preprocessorExtension.getUserFunctionArity(userFunctionName);
624+
if (arities.isEmpty()) {
625+
throw context.makeException(
626+
"Empty arity set for preprocessor extension processing the user functions [" +
627+
userFunctionName + ']', null);
628+
}
629+
result = new FunctionDefinedByUser(userFunctionName, arities, context);
622630
}
623631
} else if ("true".equals(str)) {
624632
result = Value.BOOLEAN_TRUE;

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,18 @@ public boolean isEmpty() {
6262
*/
6363
public void addItem(final ExpressionItem item) {
6464
if (item == null) {
65-
throw new PreprocessorException("[Expression]Item is null", this.sources, this.includeStack,
65+
throw new PreprocessorException(
66+
"[Expression]Item is null",
67+
this.sources,
68+
this.includeStack,
6669
null);
6770
}
6871

69-
if (last.isEmptySlot()) {
70-
last = new ExpressionTreeElement(item, this.includeStack, this.sources);
72+
if (this.last.isEmptySlot()) {
73+
this.last = new ExpressionTreeElement(item, this.includeStack, this.sources);
7174
} else {
72-
last = last.addTreeElement(new ExpressionTreeElement(item, this.includeStack, this.sources));
75+
this.last = this.last.addTreeElement(
76+
new ExpressionTreeElement(item, this.includeStack, this.sources));
7377
}
7478
}
7579

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

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public class ExpressionTreeElement {
5252
*/
5353
private static final ExpressionTreeElement[] EMPTY = new ExpressionTreeElement[0];
5454
public static final int ANY_ARITY = -1;
55-
private static final int MAX_FUNCTION_ARGUMENTS = 256;
55+
public static final int MAX_FUNCTION_ARGUMENTS = 256;
5656
/**
5757
* Contains the source string for the expression.
5858
*/
@@ -88,10 +88,16 @@ public class ExpressionTreeElement {
8888
*/
8989
private Set<Integer> expectedArities = Set.of();
9090

91+
@Override
92+
public String toString() {
93+
return "ExpressionTreeElement(item=" + this.savedItem + ",slots=" + childrenSlots.length + ")";
94+
}
95+
9196
private ExpressionTreeElement() {
9297
this.sourceString = "";
9398
this.includeStack = new FilePositionInfo[0];
9499
}
100+
95101
/**
96102
* The constructor
97103
*
@@ -108,7 +114,6 @@ private ExpressionTreeElement() {
108114
throw new PreprocessorException("[Expression]The item is null", this.sourceString,
109115
this.includeStack, null);
110116
}
111-
112117
if (item.getExpressionItemType() == ExpressionItemType.OPERATOR) {
113118
final int arity = ((AbstractOperator) item).getArity();
114119
this.expectedArities = Set.of(arity);
@@ -159,7 +164,7 @@ public boolean isEmptySlot() {
159164
}
160165

161166
private void assertNotEmptySlot() {
162-
if (isEmptySlot()) {
167+
if (this.isEmptySlot()) {
163168
throw new UnsupportedOperationException("Unsupported operation for empty slot");
164169
}
165170
}
@@ -168,7 +173,7 @@ private void assertNotEmptySlot() {
168173
* Internal auxiliary function to set the maximum priority the element
169174
*/
170175
void makeMaxPriority() {
171-
priority = ExpressionItemPriority.VALUE.getPriority();
176+
this.priority = ExpressionItemPriority.VALUE.getPriority();
172177
}
173178

174179
/**
@@ -188,7 +193,7 @@ public ExpressionItem getItem() {
188193
*/
189194

190195
public ExpressionTreeElement getParent() {
191-
return parentTreeElement;
196+
return this.parentTreeElement;
192197
}
193198

194199
/**
@@ -239,20 +244,16 @@ public boolean replaceElement(final ExpressionTreeElement oldOne,
239244
this.includeStack, null);
240245
}
241246

242-
boolean result = false;
243-
244-
final ExpressionTreeElement[] children = childrenSlots;
245-
final int len = children.length;
246-
247-
for (int i = 0; i < len; i++) {
248-
if (children[i] == oldOne) {
249-
children[i] = newOne;
247+
boolean replaced = false;
248+
for (int i = 0; i < this.childrenSlots.length; i++) {
249+
if (this.childrenSlots[i] == oldOne) {
250+
this.childrenSlots[i] = newOne;
250251
newOne.parentTreeElement = this;
251-
result = true;
252+
replaced = true;
252253
break;
253254
}
254255
}
255-
return result;
256+
return replaced;
256257
}
257258

258259
/**
@@ -298,11 +299,12 @@ public ExpressionTreeElement addTreeElement(final ExpressionTreeElement element)
298299
}
299300
if (element.nextChildSlotIndex >= element.childrenSlots.length) {
300301
throw new PreprocessorException(
301-
"[Expression]Can't process expression item, may be wrong number of arguments",
302+
"[Expression] Can't add slot data, may be wrong number of arguments, slot index is " +
303+
element.nextChildSlotIndex +
304+
" but maximum slots is " + element.childrenSlots.length,
302305
this.sourceString, this.includeStack, null);
303306
}
304-
element.childrenSlots[element.nextChildSlotIndex] = this;
305-
element.nextChildSlotIndex++;
307+
element.childrenSlots[element.nextChildSlotIndex++] = this;
306308
this.parentTreeElement = element;
307309
result = element;
308310
} else if (this.isFull()) {
@@ -387,7 +389,7 @@ private void addElementToNextFreeSlot(final ExpressionTreeElement element) {
387389
this.includeStack, null);
388390
}
389391

390-
if (childrenSlots.length == 0) {
392+
if (this.childrenSlots.length == 0) {
391393
throw new PreprocessorException(
392394
"[Expression]Unexpected element, may be unknown function [" + savedItem.toString() + ']',
393395
this.sourceString, this.includeStack, null);
@@ -410,21 +412,21 @@ public void postProcess() {
410412
switch (savedItem.getExpressionItemType()) {
411413
case OPERATOR: {
412414
if (savedItem == OPERATOR_SUB) {
413-
if (!childrenSlots[0].isEmptySlot() && childrenSlots[1].isEmptySlot()) {
414-
final ExpressionTreeElement left = childrenSlots[0];
415+
if (!this.childrenSlots[0].isEmptySlot() && this.childrenSlots[1].isEmptySlot()) {
416+
final ExpressionTreeElement left = this.childrenSlots[0];
415417
final ExpressionItem item = left.getItem();
416418
if (item.getExpressionItemType() == ExpressionItemType.VALUE) {
417419
final Value val = (Value) item;
418420
switch (val.getType()) {
419421
case INT: {
420-
childrenSlots = EMPTY;
421-
savedItem = Value.valueOf(-val.asLong());
422+
this.childrenSlots = EMPTY;
423+
this.savedItem = Value.valueOf(-val.asLong());
422424
makeMaxPriority();
423425
}
424426
break;
425427
case FLOAT: {
426-
childrenSlots = EMPTY;
427-
savedItem = Value.valueOf(0.0f - val.asFloat());
428+
this.childrenSlots = EMPTY;
429+
this.savedItem = Value.valueOf(0.0f - val.asFloat());
428430
makeMaxPriority();
429431
}
430432
break;
@@ -437,14 +439,14 @@ public void postProcess() {
437439
}
438440
}
439441
} else {
440-
for (final ExpressionTreeElement element : childrenSlots) {
442+
for (final ExpressionTreeElement element : this.childrenSlots) {
441443
if (!element.isEmptySlot()) {
442444
element.postProcess();
443445
}
444446
}
445447
}
446448
} else {
447-
for (final ExpressionTreeElement element : childrenSlots) {
449+
for (final ExpressionTreeElement element : this.childrenSlots) {
448450
if (!element.isEmptySlot()) {
449451
element.postProcess();
450452
}
@@ -453,7 +455,7 @@ public void postProcess() {
453455
}
454456
break;
455457
case FUNCTION: {
456-
for (final ExpressionTreeElement element : childrenSlots) {
458+
for (final ExpressionTreeElement element : this.childrenSlots) {
457459
if (!element.isEmptySlot()) {
458460
element.postProcess();
459461
}

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

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

2222
package com.igormaznitsa.jcp.expression.functions;
2323

24+
import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY;
25+
2426
import com.igormaznitsa.jcp.expression.ExpressionItem;
2527
import com.igormaznitsa.jcp.expression.ExpressionItemPriority;
2628
import com.igormaznitsa.jcp.expression.ExpressionItemType;
@@ -50,7 +52,7 @@
5052
*/
5153
public abstract class AbstractFunction implements ExpressionItem {
5254

53-
public static final Set<Integer> ARITY_ANY = Set.of(-1);
55+
public static final Set<Integer> ARITY_ANY = Set.of(ANY_ARITY);
5456
public static final Set<Integer> ARITY_0 = Set.of(0);
5557
public static final Set<Integer> ARITY_1 = Set.of(1);
5658
public static final Set<Integer> ARITY_1_2 = Set.of(1, 2);

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

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@
2121

2222
package com.igormaznitsa.jcp.expression.functions;
2323

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

2627
import com.igormaznitsa.jcp.context.PreprocessorContext;
2728
import com.igormaznitsa.jcp.expression.Value;
2829
import com.igormaznitsa.jcp.expression.ValueType;
2930
import com.igormaznitsa.jcp.extension.PreprocessorExtension;
30-
import java.util.Arrays;
31+
import java.util.ArrayList;
3132
import java.util.List;
3233
import java.util.Set;
3334
import java.util.stream.Collectors;
35+
import java.util.stream.IntStream;
3436

3537
/**
3638
* The class implements the user defined function handler (a function which name
@@ -40,9 +42,19 @@
4042
*/
4143
public final class FunctionDefinedByUser extends AbstractFunction {
4244

45+
private static final List<ValueType> ARGS_0 = List.of();
46+
private static final List<ValueType> ARGS_1 = List.of(ValueType.ANY);
47+
private static final List<ValueType> ARGS_2 = List.of(ValueType.ANY, ValueType.ANY);
48+
private static final List<ValueType> ARGS_3 =
49+
List.of(ValueType.ANY, ValueType.ANY, ValueType.ANY);
50+
private static final List<ValueType> ARGS_4 =
51+
List.of(ValueType.ANY, ValueType.ANY, ValueType.ANY, ValueType.ANY);
52+
private static final List<ValueType> ARGS_5 =
53+
List.of(ValueType.ANY, ValueType.ANY, ValueType.ANY, ValueType.ANY, ValueType.ANY);
54+
4355
private final String name;
4456
private final Set<Integer> allowedArities;
45-
private final List<List<ValueType>> argTypes;
57+
private final List<List<ValueType>> argVariants;
4658

4759
public FunctionDefinedByUser(final String name, final Set<Integer> allowedArities,
4860
final PreprocessorContext context) {
@@ -52,16 +64,42 @@ public FunctionDefinedByUser(final String name, final Set<Integer> allowedAritie
5264

5365
this.name = name;
5466
this.allowedArities = Set.copyOf(allowedArities);
55-
56-
this.argTypes = allowedArities.stream().map(x -> {
57-
final ValueType[] types = new ValueType[x];
58-
Arrays.fill(types, ValueType.ANY);
59-
return List.of(types);
60-
}).collect(Collectors.toUnmodifiableList());
67+
if (this.allowedArities.contains(ANY_ARITY)) {
68+
this.argVariants = List.of();
69+
} else {
70+
this.argVariants = new ArrayList<>();
71+
for (final int arity : this.allowedArities) {
72+
final List<ValueType> record;
73+
switch (arity) {
74+
case 0:
75+
record = ARGS_0;
76+
break;
77+
case 1:
78+
record = ARGS_1;
79+
break;
80+
case 2:
81+
record = ARGS_2;
82+
break;
83+
case 3:
84+
record = ARGS_3;
85+
break;
86+
case 4:
87+
record = ARGS_4;
88+
break;
89+
case 5:
90+
record = ARGS_5;
91+
break;
92+
default: {
93+
record = IntStream.of(arity).mapToObj(x -> ValueType.ANY).collect(Collectors.toList());
94+
}
95+
break;
96+
}
97+
this.argVariants.add(record);
98+
}
99+
}
61100
}
62101

63102
@Override
64-
65103
public String getName() {
66104
return name;
67105
}
@@ -96,7 +134,7 @@ public Value execute(final PreprocessorContext context, final List<Value> values
96134

97135
@Override
98136
public List<List<ValueType>> getAllowedArgumentTypes() {
99-
return this.argTypes;
137+
return this.argVariants;
100138
}
101139

102140
@Override

0 commit comments

Comments
 (0)