SLING-7682 - Add support for data-sly-list and data-sly-repeat iteration control
* implemented code changes
* updated HTL TCK module to current snapshot
diff --git a/pom.xml b/pom.xml
index ce2529a..6e9b88c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,7 +37,7 @@
The versioning scheme defined here corresponds to SLING-7406 (<module_version>-<htl_specification_version>). Take care when
releasing to only increase the first part, unless the module provides support for a newer version of the HTL specification.
-->
- <version>1.0.21-1.3.1-SNAPSHOT</version>
+ <version>1.0.21-1.4.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>Apache Sling Scripting HTL Compiler</name>
@@ -85,7 +85,8 @@
io.sightly.compiler; version:Version=1.1,
io.sightly.compiler; version:Version=1.2,
io.sightly.compiler; version:Version=1.3,
- io.sightly.compiler; version:Version=1.3.1
+ io.sightly.compiler; version:Version=1.3.1,
+ io.sightly.compiler; version:Version=1.4.0
</Provide-Capability>
</instructions>
</configuration>
diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/Loop.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/Loop.java
index 74dd016..4b3cc8c 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/Loop.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/Loop.java
@@ -28,11 +28,21 @@
private String listVariable;
private String itemVariable;
private String indexVariable;
+ private String beginVariable;
+ private String stepVariable;
+ private String endVariable;
public Start(String listVariable, String itemVariable, String indexVariable) {
+ this(listVariable, itemVariable, indexVariable, null, null, null);
+ }
+
+ public Start(String listVariable, String itemVariable, String indexVariable, String beginVariable, String stepVariable, String endVariable) {
this.listVariable = listVariable;
this.itemVariable = itemVariable;
this.indexVariable = indexVariable;
+ this.beginVariable = beginVariable;
+ this.stepVariable = stepVariable;
+ this.endVariable = endVariable;
}
public String getListVariable() {
@@ -47,6 +57,18 @@
return indexVariable;
}
+ public String getBeginVariable() {
+ return beginVariable;
+ }
+
+ public String getStepVariable() {
+ return stepVariable;
+ }
+
+ public String getEndVariable() {
+ return endVariable;
+ }
+
@Override
public void accept(CommandVisitor visitor) {
visitor.visit(this);
@@ -58,6 +80,9 @@
"listVariable='" + listVariable + '\'' +
", itemVariable='" + itemVariable + '\'' +
", indexVariable='" + indexVariable + '\'' +
+ ", beginVariable='" + beginVariable + '\'' +
+ ", stepVariable='" + stepVariable + '\'' +
+ ", endVariable='" + endVariable + '\'' +
'}';
}
}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/package-info.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/package-info.java
index dd2f081..7656a51 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/package-info.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/commands/package-info.java
@@ -21,7 +21,7 @@
* The {@code org.apache.sling.scripting.sightly.compiler.commands} package defines the API for
* {@link org.apache.sling.scripting.sightly.compiler.commands.Command} processing.
*/
-@Version("1.0.0")
+@Version("1.1.0")
package org.apache.sling.scripting.sightly.compiler.commands;
import org.osgi.annotation.versioning.Version;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/util/VariableTracker.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/util/VariableTracker.java
index 54c4189..1157486 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/compiler/util/VariableTracker.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/util/VariableTracker.java
@@ -50,14 +50,16 @@
* @param data the data associated with the variable
*/
public void pushVariable(String name, T data) {
- name = name.toLowerCase();
- Stack<T> dataStack = variableData.get(name);
- if (dataStack == null) {
- dataStack = new Stack<>();
- variableData.put(name, dataStack);
+ if (name != null) {
+ name = name.toLowerCase();
+ Stack<T> dataStack = variableData.get(name);
+ if (dataStack == null) {
+ dataStack = new Stack<>();
+ variableData.put(name, dataStack);
+ }
+ dataStack.push(data);
+ declarationStack.push(name);
}
- dataStack.push(data);
- declarationStack.push(name);
}
/**
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/visitor/TrackingVisitor.java b/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/visitor/TrackingVisitor.java
index 246a8c9..2f773d9 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/visitor/TrackingVisitor.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/visitor/TrackingVisitor.java
@@ -47,6 +47,9 @@
super.visit(loopStart);
tracker.pushVariable(loopStart.getIndexVariable(), assignDefault(loopStart));
tracker.pushVariable(loopStart.getItemVariable(), assignDefault(loopStart));
+ tracker.pushVariable(loopStart.getBeginVariable(), assignDefault(loopStart));
+ tracker.pushVariable(loopStart.getStepVariable(), assignDefault(loopStart));
+ tracker.pushVariable(loopStart.getEndVariable(), assignDefault(loopStart));
}
@Override
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/AbstractRepeatPlugin.java b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/AbstractRepeatPlugin.java
new file mode 100644
index 0000000..801d4e8
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/AbstractRepeatPlugin.java
@@ -0,0 +1,71 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.scripting.sightly.impl.plugin;
+
+import java.util.HashMap;
+
+import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperation;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.Identifier;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.NumericConstant;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperation;
+import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperator;
+
+public abstract class AbstractRepeatPlugin extends AbstractPlugin {
+
+ protected static final String INDEX = "index";
+ protected static final String COUNT = "count";
+ protected static final String FIRST = "first";
+ protected static final String MIDDLE = "middle";
+ protected static final String LAST = "last";
+ protected static final String ODD = "odd";
+ protected static final String EVEN = "even";
+ protected static final String BEGIN = "begin";
+ protected static final String STEP = "step";
+ protected static final String END = "end";
+
+ protected MapLiteral buildStatusObj(String indexVar, String sizeVar) {
+ HashMap<String, ExpressionNode> obj = new HashMap<>();
+ Identifier indexId = new Identifier(indexVar);
+ BinaryOperation firstExpr = new BinaryOperation(BinaryOperator.EQ, indexId, NumericConstant.ZERO);
+ BinaryOperation lastExpr = new BinaryOperation(
+ BinaryOperator.EQ,
+ indexId,
+ new BinaryOperation(BinaryOperator.SUB, new Identifier(sizeVar), NumericConstant.ONE));
+ obj.put(INDEX, indexId);
+ obj.put(COUNT, new BinaryOperation(BinaryOperator.ADD, indexId, NumericConstant.ONE));
+ obj.put(FIRST, firstExpr);
+ obj.put(MIDDLE, new UnaryOperation(
+ UnaryOperator.NOT,
+ new BinaryOperation(BinaryOperator.OR, firstExpr, lastExpr)));
+ obj.put(LAST, lastExpr);
+ obj.put(ODD, parityCheck(indexId, NumericConstant.ZERO));
+ obj.put(EVEN, parityCheck(indexId, NumericConstant.ONE));
+ return new MapLiteral(obj);
+ }
+
+ private ExpressionNode parityCheck(ExpressionNode numericExpression, NumericConstant expected) {
+ return new BinaryOperation(
+ BinaryOperator.EQ,
+ new BinaryOperation(BinaryOperator.REM, numericExpression, NumericConstant.TWO),
+ expected);
+ }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ListPlugin.java b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ListPlugin.java
index 6a62c5a..a613a69 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ListPlugin.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ListPlugin.java
@@ -18,33 +18,24 @@
******************************************************************************/
package org.apache.sling.scripting.sightly.impl.plugin;
-import java.util.HashMap;
+import java.util.Map;
-import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
+import org.apache.sling.scripting.sightly.compiler.commands.Conditional;
+import org.apache.sling.scripting.sightly.compiler.commands.Loop;
+import org.apache.sling.scripting.sightly.compiler.commands.VariableBinding;
import org.apache.sling.scripting.sightly.compiler.expression.Expression;
import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperation;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.Identifier;
-import org.apache.sling.scripting.sightly.compiler.expression.nodes.MapLiteral;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.NumericConstant;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperation;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperator;
-import org.apache.sling.scripting.sightly.compiler.commands.Conditional;
-import org.apache.sling.scripting.sightly.compiler.commands.Loop;
-import org.apache.sling.scripting.sightly.compiler.commands.VariableBinding;
-import org.apache.sling.scripting.sightly.impl.compiler.frontend.CompilerContext;
import org.apache.sling.scripting.sightly.impl.compiler.PushStream;
+import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
+import org.apache.sling.scripting.sightly.impl.compiler.frontend.CompilerContext;
-public class ListPlugin extends AbstractPlugin {
-
- private static final String INDEX = "index";
- private static final String COUNT = "count";
- private static final String FIRST = "first";
- private static final String MIDDLE = "middle";
- private static final String LAST = "last";
- private static final String ODD = "odd";
- private static final String EVEN = "even";
+public class ListPlugin extends AbstractRepeatPlugin {
public ListPlugin() {
name = "list";
@@ -57,14 +48,51 @@
private String listVariable = compilerContext.generateVariable("collectionVar");
private String collectionSizeVar = compilerContext.generateVariable("size");
+ private String collectionNotEmpty = compilerContext.generateVariable("notEmpty");
+ private String beginVariable = compilerContext.generateVariable(BEGIN);
+ private String stepVariable = compilerContext.generateVariable(STEP);
+ private String endVariable = compilerContext.generateVariable(END);
+ private String validStartStepEnd = compilerContext.generateVariable("validStartStepEnd");
@Override
public void beforeElement(PushStream stream, String tagName) {
stream.write(new VariableBinding.Start(listVariable, expression.getRoot()));
stream.write(new VariableBinding.Start(collectionSizeVar,
new UnaryOperation(UnaryOperator.LENGTH, new Identifier(listVariable))));
- stream.write(new Conditional.Start(collectionSizeVar, true));
-
+ stream.write(new VariableBinding.Start(collectionNotEmpty, new BinaryOperation(BinaryOperator.GT, new Identifier
+ (collectionSizeVar), NumericConstant.ZERO)));
+ stream.write(new Conditional.Start(collectionNotEmpty, true));
+ Map<String, ExpressionNode> options = expression.getOptions();
+ if (options.containsKey(BEGIN)) {
+ stream.write(new VariableBinding.Start(beginVariable, expression.getOptions().get(BEGIN)));
+ } else {
+ stream.write(new VariableBinding.Start(beginVariable, NumericConstant.ZERO));
+ }
+ if (options.containsKey(STEP)) {
+ stream.write(new VariableBinding.Start(stepVariable, expression.getOptions().get(STEP)));
+ } else {
+ stream.write(new VariableBinding.Start(stepVariable, NumericConstant.ONE));
+ }
+ if (options.containsKey(END)) {
+ stream.write(new VariableBinding.Start(endVariable, expression.getOptions().get(END)));
+ } else {
+ stream.write(new VariableBinding.Start(endVariable, new Identifier(collectionSizeVar)));
+ }
+ stream.write(new VariableBinding.Start(validStartStepEnd,
+ new BinaryOperation(BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.LT, new Identifier(beginVariable), new Identifier(collectionSizeVar)),
+ new BinaryOperation(
+ BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.GEQ, new Identifier(beginVariable), NumericConstant.ZERO),
+ new BinaryOperation(BinaryOperator.GT, new Identifier(stepVariable), NumericConstant.ZERO)
+ )
+ ),
+ new BinaryOperation(BinaryOperator.GT, new Identifier(endVariable), NumericConstant.ZERO)
+ )
+ )
+ );
+ stream.write(new Conditional.Start(validStartStepEnd, true));
}
@Override
@@ -74,10 +102,39 @@
String indexVariable = compilerContext.generateVariable("index");
stream.write(new Loop.Start(listVariable, itemVariable, indexVariable));
stream.write(new VariableBinding.Start(loopStatusVar, buildStatusObj(indexVariable, collectionSizeVar)));
+ String stepConditionVariable = compilerContext.generateVariable("stepCondition");
+ stream.write(new VariableBinding.Start(stepConditionVariable,
+ new BinaryOperation(
+ BinaryOperator.REM,
+ new BinaryOperation(
+ BinaryOperator.SUB,
+ new Identifier(indexVariable),
+ new Identifier(beginVariable)
+ ),
+ new Identifier(stepVariable))
+ )
+ );
+ String loopTraversalVariable = compilerContext.generateVariable("traversal");
+ stream.write(new VariableBinding.Start(loopTraversalVariable,
+ new BinaryOperation(
+ BinaryOperator.AND,
+ new BinaryOperation(
+ BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.GEQ, new Identifier(indexVariable), new Identifier(beginVariable)),
+ new BinaryOperation(BinaryOperator.LEQ, new Identifier(indexVariable), new Identifier(endVariable))
+ ),
+ new BinaryOperation(BinaryOperator.EQ, new Identifier(stepConditionVariable), NumericConstant.ZERO)
+ )
+ )
+ );
+ stream.write(new Conditional.Start(loopTraversalVariable, true));
}
@Override
public void afterChildren(PushStream stream) {
+ stream.write(Conditional.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
stream.write(VariableBinding.END);
stream.write(Loop.END);
}
@@ -87,6 +144,12 @@
stream.write(Conditional.END);
stream.write(VariableBinding.END);
stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
+ stream.write(Conditional.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
}
@@ -97,33 +160,6 @@
}
return Syntax.DEFAULT_LIST_ITEM_VAR_NAME;
}
-
- private MapLiteral buildStatusObj(String indexVar, String sizeVar) {
- HashMap<String, ExpressionNode> obj = new HashMap<>();
- Identifier indexId = new Identifier(indexVar);
- BinaryOperation firstExpr = new BinaryOperation(BinaryOperator.EQ, indexId, NumericConstant.ZERO);
- BinaryOperation lastExpr = new BinaryOperation(
- BinaryOperator.EQ,
- indexId,
- new BinaryOperation(BinaryOperator.SUB, new Identifier(sizeVar), NumericConstant.ONE));
- obj.put(INDEX, indexId);
- obj.put(COUNT, new BinaryOperation(BinaryOperator.ADD, indexId, NumericConstant.ONE));
- obj.put(FIRST, firstExpr);
- obj.put(MIDDLE, new UnaryOperation(
- UnaryOperator.NOT,
- new BinaryOperation(BinaryOperator.OR, firstExpr, lastExpr)));
- obj.put(LAST, lastExpr);
- obj.put(ODD, parityCheck(indexId, NumericConstant.ZERO));
- obj.put(EVEN, parityCheck(indexId, NumericConstant.ONE));
- return new MapLiteral(obj);
- }
-
- private ExpressionNode parityCheck(ExpressionNode numericExpression, NumericConstant expected) {
- return new BinaryOperation(
- BinaryOperator.EQ,
- new BinaryOperation(BinaryOperator.REM, numericExpression, NumericConstant.TWO),
- expected);
- }
};
}
}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/RepeatPlugin.java b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/RepeatPlugin.java
index e8ca678..ff8d41d 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/RepeatPlugin.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/RepeatPlugin.java
@@ -18,34 +18,26 @@
******************************************************************************/
package org.apache.sling.scripting.sightly.impl.plugin;
-import java.util.HashMap;
+import java.util.Map;
+import org.apache.sling.scripting.sightly.compiler.commands.Conditional;
+import org.apache.sling.scripting.sightly.compiler.commands.Loop;
import org.apache.sling.scripting.sightly.compiler.commands.OutText;
-import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
+import org.apache.sling.scripting.sightly.compiler.commands.VariableBinding;
import org.apache.sling.scripting.sightly.compiler.expression.Expression;
import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperation;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.Identifier;
-import org.apache.sling.scripting.sightly.compiler.expression.nodes.MapLiteral;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.NumericConstant;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperation;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperator;
-import org.apache.sling.scripting.sightly.impl.compiler.frontend.CompilerContext;
-import org.apache.sling.scripting.sightly.compiler.commands.Conditional;
-import org.apache.sling.scripting.sightly.compiler.commands.Loop;
-import org.apache.sling.scripting.sightly.compiler.commands.VariableBinding;
import org.apache.sling.scripting.sightly.impl.compiler.PushStream;
+import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
+import org.apache.sling.scripting.sightly.impl.compiler.frontend.CompilerContext;
-public class RepeatPlugin extends AbstractPlugin {
+public class RepeatPlugin extends AbstractRepeatPlugin {
- private static final String INDEX = "index";
- private static final String COUNT = "count";
- private static final String FIRST = "first";
- private static final String MIDDLE = "middle";
- private static final String LAST = "last";
- private static final String ODD = "odd";
- private static final String EVEN = "even";
private static final OutText NEW_LINE = new OutText("\n");
public RepeatPlugin() {
@@ -59,18 +51,83 @@
private String listVariable = compilerContext.generateVariable("collectionVar");
private String collectionSizeVar = compilerContext.generateVariable("size");
+ private String collectionNotEmpty = compilerContext.generateVariable("notEmpty");
+ private String beginVariable = compilerContext.generateVariable(BEGIN);
+ private String stepVariable = compilerContext.generateVariable(STEP);
+ private String endVariable = compilerContext.generateVariable(END);
+ private String validStartStepEnd = compilerContext.generateVariable("validStartStepEnd");
@Override
public void beforeElement(PushStream stream, String tagName) {
stream.write(new VariableBinding.Start(listVariable, expression.getRoot()));
stream.write(new VariableBinding.Start(collectionSizeVar,
new UnaryOperation(UnaryOperator.LENGTH, new Identifier(listVariable))));
- stream.write(new Conditional.Start(collectionSizeVar, true));
+ stream.write(new VariableBinding.Start(collectionNotEmpty, new BinaryOperation(BinaryOperator.GT, new Identifier
+ (collectionSizeVar), NumericConstant.ZERO)));
+ stream.write(new Conditional.Start(collectionNotEmpty, true));
+ Map<String, ExpressionNode> options = expression.getOptions();
+ if (options.containsKey(BEGIN)) {
+ stream.write(new VariableBinding.Start(beginVariable, expression.getOptions().get(BEGIN)));
+ } else {
+ stream.write(new VariableBinding.Start(beginVariable, NumericConstant.ZERO));
+ }
+ if (options.containsKey(STEP)) {
+ stream.write(new VariableBinding.Start(stepVariable, expression.getOptions().get(STEP)));
+ } else {
+ stream.write(new VariableBinding.Start(stepVariable, NumericConstant.ONE));
+ }
+ if (options.containsKey(END)) {
+ stream.write(new VariableBinding.Start(endVariable, expression.getOptions().get(END)));
+ } else {
+ stream.write(new VariableBinding.Start(endVariable, new Identifier(collectionSizeVar)));
+ }
+ stream.write(new VariableBinding.Start(validStartStepEnd,
+ new BinaryOperation(BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.LT, new Identifier(beginVariable), new Identifier(collectionSizeVar)),
+ new BinaryOperation(
+ BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.GEQ, new Identifier(beginVariable), NumericConstant.ZERO),
+ new BinaryOperation(BinaryOperator.GT, new Identifier(stepVariable), NumericConstant.ZERO)
+ )
+ ),
+ new BinaryOperation(BinaryOperator.GT, new Identifier(endVariable), NumericConstant.ZERO)
+ )
+ )
+ );
+ stream.write(new Conditional.Start(validStartStepEnd, true));
String itemVariable = decodeItemVariable();
String loopStatusVar = Syntax.itemLoopStatusVariable(itemVariable);
String indexVariable = compilerContext.generateVariable("index");
stream.write(new Loop.Start(listVariable, itemVariable, indexVariable));
stream.write(new VariableBinding.Start(loopStatusVar, buildStatusObj(indexVariable, collectionSizeVar)));
+ String stepConditionVariable = compilerContext.generateVariable("stepCondition");
+ stream.write(new VariableBinding.Start(stepConditionVariable,
+ new BinaryOperation(
+ BinaryOperator.REM,
+ new BinaryOperation(
+ BinaryOperator.SUB,
+ new Identifier(indexVariable),
+ new Identifier(beginVariable)
+ ),
+ new Identifier(stepVariable))
+ )
+ );
+ String loopTraversalVariable = compilerContext.generateVariable("traversal");
+ stream.write(new VariableBinding.Start(loopTraversalVariable,
+ new BinaryOperation(
+ BinaryOperator.AND,
+ new BinaryOperation(
+ BinaryOperator.AND,
+ new BinaryOperation(BinaryOperator.GEQ, new Identifier(indexVariable), new Identifier(
+ beginVariable)),
+ new BinaryOperation(BinaryOperator.LEQ, new Identifier(indexVariable), new Identifier(endVariable))
+ ),
+ new BinaryOperation(BinaryOperator.EQ, new Identifier(stepConditionVariable), NumericConstant.ZERO)
+ )
+ )
+ );
+ stream.write(new Conditional.Start(loopTraversalVariable, true));
}
@@ -81,11 +138,20 @@
@Override
public void afterElement(PushStream stream) {
+ stream.write(Conditional.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
stream.write(VariableBinding.END);
stream.write(Loop.END);
stream.write(Conditional.END);
stream.write(VariableBinding.END);
stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
+ stream.write(Conditional.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
+ stream.write(VariableBinding.END);
}
@@ -97,26 +163,6 @@
return Syntax.DEFAULT_LIST_ITEM_VAR_NAME;
}
- private MapLiteral buildStatusObj(String indexVar, String sizeVar) {
- HashMap<String, ExpressionNode> obj = new HashMap<>();
- Identifier indexId = new Identifier(indexVar);
- BinaryOperation firstExpr = new BinaryOperation(BinaryOperator.EQ, indexId, NumericConstant.ZERO);
- BinaryOperation lastExpr = new BinaryOperation(
- BinaryOperator.EQ,
- indexId,
- new BinaryOperation(BinaryOperator.SUB, new Identifier(sizeVar), NumericConstant.ONE));
- obj.put(INDEX, indexId);
- obj.put(COUNT, new BinaryOperation(BinaryOperator.ADD, indexId, NumericConstant.ONE));
- obj.put(FIRST, firstExpr);
- obj.put(MIDDLE, new UnaryOperation(
- UnaryOperator.NOT,
- new BinaryOperation(BinaryOperator.OR, firstExpr, lastExpr)));
- obj.put(LAST, lastExpr);
- obj.put(ODD, parityCheck(indexId, NumericConstant.ZERO));
- obj.put(EVEN, parityCheck(indexId, NumericConstant.ONE));
- return new MapLiteral(obj);
- }
-
private ExpressionNode parityCheck(ExpressionNode numericExpression, NumericConstant expected) {
return new BinaryOperation(
BinaryOperator.EQ,