From a4ffaa6e7a5660071dbd84d0de641321e7124b3a Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 6 Jun 2016 13:53:31 -0700 Subject: [PATCH] Working iterable foreach with tests. --- .../src/main/antlr/PainlessParser.g4 | 2 +- .../org/elasticsearch/painless/antlr/Walker.java | 2 +- .../org/elasticsearch/painless/node/SEach.java | 15 +++++++++++---- .../painless/BasicStatementTests.java | 9 +++++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/modules/lang-painless/src/main/antlr/PainlessParser.g4 b/modules/lang-painless/src/main/antlr/PainlessParser.g4 index dad8db62117..6a5ea6bf7fe 100644 --- a/modules/lang-painless/src/main/antlr/PainlessParser.g4 +++ b/modules/lang-painless/src/main/antlr/PainlessParser.g4 @@ -74,7 +74,7 @@ decltype ; funcref - : TYPE REF ID + : ( TYPE | ID ) REF ID ; declvar diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java index a309fccdd27..4ac090a4228 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/Walker.java @@ -279,7 +279,7 @@ public final class Walker extends PainlessParserBaseVisitor { String type = ctx.decltype().getText(); String name = ctx.ID().getText(); - AExpression expression = (AExpression)visit(ctx.expression()); + AExpression expression = (AExpression)visitExpression(ctx.expression()); SBlock block = (SBlock)visit(ctx.trailer()); return new SEach(location(ctx), settings.getMaxLoopCounter(), type, name, expression, block); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java index 8d4052326fc..d7942583387 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java @@ -33,6 +33,9 @@ import org.elasticsearch.painless.Variables.Variable; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; +import java.util.HashMap; +import java.util.Map; + public class SEach extends AStatement { final int maxLoopCounter; @@ -85,7 +88,7 @@ public class SEach extends AStatement { Type itr = Definition.getType("Iterator"); - variable = variables.addVariable(location, type, name, false, false); + variable = variables.addVariable(location, type, name, true, false); iterator = variables.addVariable(location, itr, "#itr" + location.getOffset(), true, false); method = expression.actual.struct.methods.get(new MethodKey("iterator", 0)); @@ -107,11 +110,11 @@ public class SEach extends AStatement { if (next == null) { throw location.createError(new IllegalArgumentException("Method [next] does not exist for type [Iterator].")); - } else if (next.rtn.sort != Sort.OBJECT) { - throw location.createError(new IllegalArgumentException("Method [next] does not return type [Object].")); + } else if (next.rtn.sort != Sort.DEF) { + throw location.createError(new IllegalArgumentException("Method [next] does not return type [def].")); } - cast = AnalyzerCaster.getLegalCast(location, Definition.getType("Object"), type, true, true); + cast = AnalyzerCaster.getLegalCast(location, Definition.DEF_TYPE, type, true, true); if (block == null) { throw location.createError(new IllegalArgumentException("Extraneous for each loop.")); @@ -150,8 +153,11 @@ public class SEach extends AStatement { writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ISTORE), iterator.slot); + Label begin = new Label(); Label end = new Label(); + writer.mark(begin); + writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.slot); writer.invokeInterface(hasNext.owner.type, hasNext.method); writer.ifZCmp(MethodWriter.EQ, end); @@ -163,6 +169,7 @@ public class SEach extends AStatement { block.write(writer); + writer.goTo(begin); writer.mark(end); } } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java index 1fffcf1ee29..7a2846433a6 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java @@ -125,9 +125,14 @@ public class BasicStatementTests extends ScriptTestCase { } } - public void testEachStatement() { + public void testIterableForEachStatement() { assertEquals(6, exec("List l = new ArrayList(); l.add(1); l.add(2); l.add(3); int total = 0;" + - " for (int x : l) total += x; return x")); + " for (int x : l) total += x; return total")); + assertEquals("123", exec("List l = new ArrayList(); l.add('1'); l.add('2'); l.add('3'); String cat = '';" + + " for (String x : l) cat += x; return cat")); + assertEquals("1236", exec("Map m = new HashMap(); m.put('1', 1); m.put('2', 2); m.put('3', 3);" + + " String cat = ''; int total = 0;" + + " for (Map.Entry e : m.entrySet()) { cat += e.getKey(); total += e.getValue(); } return cat + total")); } public void testDeclarationStatement() {