Working iterable foreach with tests.

This commit is contained in:
Jack Conradson 2016-06-06 13:53:31 -07:00
parent 64ff818f9f
commit a4ffaa6e7a
4 changed files with 20 additions and 8 deletions

View File

@ -74,7 +74,7 @@ decltype
; ;
funcref funcref
: TYPE REF ID : ( TYPE | ID ) REF ID
; ;
declvar declvar

View File

@ -279,7 +279,7 @@ public final class Walker extends PainlessParserBaseVisitor<Object> {
String type = ctx.decltype().getText(); String type = ctx.decltype().getText();
String name = ctx.ID().getText(); String name = ctx.ID().getText();
AExpression expression = (AExpression)visit(ctx.expression()); AExpression expression = (AExpression)visitExpression(ctx.expression());
SBlock block = (SBlock)visit(ctx.trailer()); SBlock block = (SBlock)visit(ctx.trailer());
return new SEach(location(ctx), settings.getMaxLoopCounter(), type, name, expression, block); return new SEach(location(ctx), settings.getMaxLoopCounter(), type, name, expression, block);

View File

@ -33,6 +33,9 @@ import org.elasticsearch.painless.Variables.Variable;
import org.objectweb.asm.Label; import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.HashMap;
import java.util.Map;
public class SEach extends AStatement { public class SEach extends AStatement {
final int maxLoopCounter; final int maxLoopCounter;
@ -85,7 +88,7 @@ public class SEach extends AStatement {
Type itr = Definition.getType("Iterator"); 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); iterator = variables.addVariable(location, itr, "#itr" + location.getOffset(), true, false);
method = expression.actual.struct.methods.get(new MethodKey("iterator", 0)); method = expression.actual.struct.methods.get(new MethodKey("iterator", 0));
@ -107,11 +110,11 @@ public class SEach extends AStatement {
if (next == null) { if (next == null) {
throw location.createError(new IllegalArgumentException("Method [next] does not exist for type [Iterator].")); throw location.createError(new IllegalArgumentException("Method [next] does not exist for type [Iterator]."));
} else if (next.rtn.sort != Sort.OBJECT) { } else if (next.rtn.sort != Sort.DEF) {
throw location.createError(new IllegalArgumentException("Method [next] does not return type [Object].")); 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) { if (block == null) {
throw location.createError(new IllegalArgumentException("Extraneous for each loop.")); 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); writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ISTORE), iterator.slot);
Label begin = new Label();
Label end = new Label(); Label end = new Label();
writer.mark(begin);
writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.slot); writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.slot);
writer.invokeInterface(hasNext.owner.type, hasNext.method); writer.invokeInterface(hasNext.owner.type, hasNext.method);
writer.ifZCmp(MethodWriter.EQ, end); writer.ifZCmp(MethodWriter.EQ, end);
@ -163,6 +169,7 @@ public class SEach extends AStatement {
block.write(writer); block.write(writer);
writer.goTo(begin);
writer.mark(end); writer.mark(end);
} }
} }

View File

@ -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;" + 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() { public void testDeclarationStatement() {