This is an automated email from the ASF dual-hosted git repository. radu pushed a commit to branch issue/SLING-7682 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-compiler.git
commit 97f42d1168b2093914f9e0842b2a40c4da8b8c4d Author: Radu Cotescu <[email protected]> AuthorDate: Fri May 25 13:27:45 2018 +0200 SLING-7682 - Add support for data-sly-list and data-sly-repeat iteration control * implemented code changes * updated HTL TCK module to current snapshot --- pom.xml | 5 +- .../scripting/sightly/compiler/commands/Loop.java | 25 ++++ .../sightly/compiler/commands/package-info.java | 2 +- .../sightly/compiler/util/VariableTracker.java | 16 +-- .../impl/compiler/visitor/TrackingVisitor.java | 3 + .../sightly/impl/plugin/AbstractRepeatPlugin.java | 71 ++++++++++++ .../scripting/sightly/impl/plugin/ListPlugin.java | 126 +++++++++++++-------- .../sightly/impl/plugin/RepeatPlugin.java | 118 +++++++++++++------ 8 files changed, 275 insertions(+), 91 deletions(-) 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 @@ public final class Loop { 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 @@ public final class Loop { 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 @@ public final class Loop { "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 @@ public final class VariableTracker<T> { * @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 @@ public abstract class TrackingVisitor<T> extends UniformVisitor { 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 @@ public class ListPlugin extends AbstractPlugin { 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 @@ public class ListPlugin extends AbstractPlugin { 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 @@ public class ListPlugin extends AbstractPlugin { 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 @@ public class ListPlugin extends AbstractPlugin { } 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 @@ public class RepeatPlugin extends AbstractPlugin { 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 @@ public class RepeatPlugin extends AbstractPlugin { @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 @@ public class RepeatPlugin extends AbstractPlugin { 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, -- To stop receiving notification emails like this one, please contact [email protected].
