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 84f44c832d3..53c98f7589e 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 @@ -109,6 +109,7 @@ import org.elasticsearch.painless.lookup.PainlessLookup; import org.elasticsearch.painless.node.AExpression; import org.elasticsearch.painless.node.ANode; import org.elasticsearch.painless.node.AStatement; +import org.elasticsearch.painless.node.DUnresolvedType; import org.elasticsearch.painless.node.EAssignment; import org.elasticsearch.painless.node.EBinary; import org.elasticsearch.painless.node.EBool; @@ -478,8 +479,9 @@ public final class Walker extends PainlessParserBaseVisitor { for (DeclvarContext declvar : ctx.declvar()) { String name = declvar.ID().getText(); AExpression expression = declvar.expression() == null ? null : (AExpression)visit(declvar.expression()); + DUnresolvedType unresolvedType = new DUnresolvedType(location(declvar), type); - declarations.add(new SDeclaration(location(declvar), type, name, expression)); + declarations.add(new SDeclaration(location(declvar), unresolvedType, name, expression)); } return new SDeclBlock(location(ctx), declarations); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java new file mode 100644 index 00000000000..223b3906867 --- /dev/null +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DResolvedType.java @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.painless.node; + +import org.elasticsearch.painless.Location; +import org.elasticsearch.painless.lookup.PainlessLookup; +import org.elasticsearch.painless.lookup.PainlessLookupUtility; + +import java.util.Objects; + +/** + * Represents a Painless type as a {@link Class}. This may still + * require resolution to ensure the type in the {@link PainlessLookup}. + */ +public class DResolvedType extends DType { + + protected final Class type; + + /** + * If set to {@code true} ensures the type is in the {@link PainlessLookup}. + * If set to {@code false} assumes the type is valid. + */ + protected final boolean checkInLookup; + + public DResolvedType(Location location, Class type) { + this(location, type, true); + } + + public DResolvedType(Location location, Class type, boolean checkInLookup) { + super(location); + this.type = Objects.requireNonNull(type); + this.checkInLookup = checkInLookup; + } + + /** + * If {@link #checkInLookup} is {@code true} checks if the type is in the + * {@link PainlessLookup}, otherwise returns {@code this}. + * @throws IllegalArgumentException if both checking the type is in the {@link PainlessLookup} + * and the type cannot be resolved from the {@link PainlessLookup} + * @return a {@link DResolvedType} where the resolved Painless type is retrievable + */ + @Override + public DResolvedType resolveType(PainlessLookup painlessLookup) { + if (checkInLookup == false) { + return this; + } + + if (painlessLookup.getClasses().contains(type) == false) { + throw location.createError(new IllegalArgumentException( + "cannot resolve type [" + PainlessLookupUtility.typeToCanonicalTypeName(type) + "]")); + } + + return new DResolvedType(location, type, false); + } + + public Class getType() { + return type; + } + + @Override + public String toString() { + return " (DResolvedType [" + PainlessLookupUtility.typeToCanonicalTypeName(type) + "])"; + } +} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DType.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DType.java new file mode 100644 index 00000000000..54707391706 --- /dev/null +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DType.java @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.painless.node; + +import org.elasticsearch.painless.Location; +import org.elasticsearch.painless.lookup.PainlessLookup; + +import java.util.Objects; + +/** + * Represents an abstract Painless type. {@link DType} nodes must be + * resolved using {@link #resolveType(PainlessLookup)} to retrieve the + * actual Painless type. {@link DType} exists as a base class so consumers + * may have either a {@link DUnresolvedType} representing a Painless + * canonical type name or a {@link DResolvedType} representing a Painless + * type as the Painless AST is constructed. This allows Painless types already + * resolved at the time of Painless AST construction to not be forced to + * convert back to a Painless canonical type name and then re-resolved. + */ +public abstract class DType { + + protected final Location location; + + public DType(Location location) { + this.location = Objects.requireNonNull(location); + } + + public abstract DResolvedType resolveType(PainlessLookup painlessLookup); +} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java new file mode 100644 index 00000000000..8e21507fdaa --- /dev/null +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/DUnresolvedType.java @@ -0,0 +1,61 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.painless.node; + +import org.elasticsearch.painless.Location; +import org.elasticsearch.painless.lookup.PainlessLookup; + +import java.util.Objects; + +/** + * Represents a canonical Painless type name as a {@link String} + * that requires resolution. + */ +public class DUnresolvedType extends DType { + + protected final String typeName; + + public DUnresolvedType(Location location, String typeName) { + super(location); + this.typeName = Objects.requireNonNull(typeName); + } + + /** + * Resolves the canonical Painless type name to a Painless type. + * @throws IllegalArgumentException if the type cannot be resolved from the {@link PainlessLookup} + * @return a {@link DResolvedType} where the resolved Painless type is retrievable + */ + @Override + public DResolvedType resolveType(PainlessLookup painlessLookup) { + Class type = painlessLookup.canonicalTypeNameToType(typeName); + + if (type == null) { + throw location.createError(new IllegalArgumentException("cannot resolve type [" + typeName + "]")); + } + + return new DResolvedType(location, type); + } + + @Override + public String toString() { + return "(DUnresolvedType [" + typeName + "])"; + } +} + diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java index de42c43db4e..e5d8f1e8811 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java @@ -36,13 +36,13 @@ import java.util.Set; */ public final class SDeclaration extends AStatement { - private final String type; + private final DType type; private final String name; private AExpression expression; private Variable variable = null; - public SDeclaration(Location location, String type, String name, AExpression expression) { + public SDeclaration(Location location, DType type, String name, AExpression expression) { super(location); this.type = Objects.requireNonNull(type); @@ -61,19 +61,15 @@ public final class SDeclaration extends AStatement { @Override void analyze(ScriptRoot scriptRoot, Locals locals) { - Class clazz = scriptRoot.getPainlessLookup().canonicalTypeNameToType(this.type); - - if (clazz == null) { - throw createError(new IllegalArgumentException("Not a type [" + this.type + "].")); - } + DResolvedType resolvedType = type.resolveType(scriptRoot.getPainlessLookup()); if (expression != null) { - expression.expected = clazz; + expression.expected = resolvedType.getType(); expression.analyze(scriptRoot, locals); expression = expression.cast(scriptRoot, locals); } - variable = locals.addVariable(location, clazz, name, false); + variable = locals.addVariable(location, resolvedType.getType(), name, false); } @Override diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java index d2832dfdfd5..562b6e1e5e9 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java @@ -54,7 +54,7 @@ public class NodeToStringTests extends ESTestCase { public void testEAssignment() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" + " (SExpression (EAssignment (EVariable i) = (ENumeric 2)))\n" + " (SReturn (EVariable i)))", "def i;\n" @@ -63,7 +63,7 @@ public class NodeToStringTests extends ESTestCase { for (String operator : new String[] {"+", "-", "*", "/", "%", "&", "^", "|", "<<", ">>", ">>>"}) { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i (ENumeric 1)))\n" + " (SExpression (EAssignment (EVariable i) " + operator + "= (ENumeric 2)))\n" + " (SReturn (EVariable i)))", "def i = 1;\n" @@ -73,31 +73,31 @@ public class NodeToStringTests extends ESTestCase { // Compound assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" + " (SReturn (EAssignment (EVariable i) = (ENumeric 2))))", "def i;\n" + "return i = 2"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" + " (SReturn (EAssignment (EVariable i) ++ post)))", "def i;\n" + "return i++"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" + " (SReturn (EAssignment (EVariable i) ++ pre)))", "def i;\n" + "return ++i"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" + " (SReturn (EAssignment (EVariable i) -- post)))", "def i;\n" + "return i--"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def i))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) i))\n" + " (SReturn (EAssignment (EVariable i) -- pre)))", "def i;\n" + "return --i"); @@ -153,7 +153,8 @@ public class NodeToStringTests extends ESTestCase { public void testECapturingFunctionRef() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration Integer x (PCallInvoke (EStatic Integer) valueOf (Args (ENumeric 5)))))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [Integer]) x " + + "(PCallInvoke (EStatic Integer) valueOf (Args (ENumeric 5)))))\n" + " (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args (ECapturingFunctionRef x toString)))))", "Integer x = Integer.valueOf(5);\n" + "return Optional.empty().orElseGet(x::toString)"); @@ -349,7 +350,7 @@ public class NodeToStringTests extends ESTestCase { assertToString("(SClass (SReturn (EVariable params)))", "return params"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def a (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) a (ENumeric 1)))\n" + " (SReturn (EVariable a)))", "def a = 1;\n" + "return a"); @@ -373,13 +374,13 @@ public class NodeToStringTests extends ESTestCase { assertToString("(SClass (SReturn (PField nullSafe (EVariable params) a)))", "return params?.a"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int[] a (ENewArray int[] dims (Args (ENumeric 10)))))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int[]]) a (ENewArray int[] dims (Args (ENumeric 10)))))\n" + " (SReturn (PField (EVariable a) length)))", "int[] a = new int[10];\n" + "return a.length"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration org.elasticsearch.painless.FeatureTestObject a" + + " (SDeclBlock (SDeclaration (DUnresolvedType [org.elasticsearch.painless.FeatureTestObject]) a" + " (ENewObj org.elasticsearch.painless.FeatureTestObject)))\n" + " (SExpression (EAssignment (PField (EVariable a) x) = (ENumeric 10)))\n" + " (SReturn (PField (EVariable a) x)))", @@ -511,13 +512,13 @@ public class NodeToStringTests extends ESTestCase { public void testSBreak() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int itr (ENumeric 2)))\n" - + " (SDeclBlock (SDeclaration int a (ENumeric 1)))\n" - + " (SDeclBlock (SDeclaration int b (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) itr (ENumeric 2)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) a (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) b (ENumeric 1)))\n" + " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n" + " (SExpression (EAssignment (EVariable itr) ++ post))\n" + " (SIf (EComp (EVariable itr) > (ENumeric 10000)) (SBlock (SBreak)))\n" - + " (SDeclBlock (SDeclaration int tmp (EVariable a)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) tmp (EVariable a)))\n" + " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n" + " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n" + " (SReturn (EVariable b)))", @@ -539,13 +540,13 @@ public class NodeToStringTests extends ESTestCase { public void testSContinue() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int itr (ENumeric 2)))\n" - + " (SDeclBlock (SDeclaration int a (ENumeric 1)))\n" - + " (SDeclBlock (SDeclaration int b (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) itr (ENumeric 2)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) a (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) b (ENumeric 1)))\n" + " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n" + " (SExpression (EAssignment (EVariable itr) ++ post))\n" + " (SIf (EComp (EVariable itr) < (ENumeric 10000)) (SBlock (SContinue)))\n" - + " (SDeclBlock (SDeclaration int tmp (EVariable a)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) tmp (EVariable a)))\n" + " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n" + " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n" + " (SReturn (EVariable b)))", @@ -567,7 +568,7 @@ public class NodeToStringTests extends ESTestCase { public void testSDeclBlock() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def a))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) a))\n" + " (SExpression (EAssignment (EVariable a) = (ENumeric 10)))\n" + " (SReturn (EVariable a)))", "def a;\n" @@ -575,34 +576,34 @@ public class NodeToStringTests extends ESTestCase { + "return a"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration def a (ENumeric 10)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [def]) a (ENumeric 10)))\n" + " (SReturn (EVariable a)))", "def a = 10;\n" + "return a"); assertToString( "(SClass\n" + " (SDeclBlock\n" - + " (SDeclaration def a)\n" - + " (SDeclaration def b)\n" - + " (SDeclaration def c))\n" + + " (SDeclaration (DUnresolvedType [def]) a)\n" + + " (SDeclaration (DUnresolvedType [def]) b)\n" + + " (SDeclaration (DUnresolvedType [def]) c))\n" + " (SReturn (EVariable a)))", "def a, b, c;\n" + "return a"); assertToString( "(SClass\n" + " (SDeclBlock\n" - + " (SDeclaration def a (ENumeric 10))\n" - + " (SDeclaration def b (ENumeric 20))\n" - + " (SDeclaration def c (ENumeric 100)))\n" + + " (SDeclaration (DUnresolvedType [def]) a (ENumeric 10))\n" + + " (SDeclaration (DUnresolvedType [def]) b (ENumeric 20))\n" + + " (SDeclaration (DUnresolvedType [def]) c (ENumeric 100)))\n" + " (SReturn (EVariable a)))", "def a = 10, b = 20, c = 100;\n" + "return a"); assertToString( "(SClass\n" + " (SDeclBlock\n" - + " (SDeclaration def a (ENumeric 10))\n" - + " (SDeclaration def b)\n" - + " (SDeclaration def c (ENumeric 100)))\n" + + " (SDeclaration (DUnresolvedType [def]) a (ENumeric 10))\n" + + " (SDeclaration (DUnresolvedType [def]) b)\n" + + " (SDeclaration (DUnresolvedType [def]) c (ENumeric 100)))\n" + " (SReturn (EVariable a)))", "def a = 10, b, c = 100;\n" + "return a"); @@ -610,9 +611,9 @@ public class NodeToStringTests extends ESTestCase { "(SClass\n" + " (SIf (PField (EVariable params) a) (SBlock\n" + " (SDeclBlock\n" - + " (SDeclaration def a (ENumeric 10))\n" - + " (SDeclaration def b)\n" - + " (SDeclaration def c (ENumeric 100)))\n" + + " (SDeclaration (DUnresolvedType [def]) a (ENumeric 10))\n" + + " (SDeclaration (DUnresolvedType [def]) b)\n" + + " (SDeclaration (DUnresolvedType [def]) c (ENumeric 100)))\n" + " (SReturn (EVariable a))))\n" + " (SReturn (EBoolean false)))", "if (params.a) {" @@ -625,12 +626,12 @@ public class NodeToStringTests extends ESTestCase { public void testSDo() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int itr (ENumeric 2)))\n" - + " (SDeclBlock (SDeclaration int a (ENumeric 1)))\n" - + " (SDeclBlock (SDeclaration int b (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) itr (ENumeric 2)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) a (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) b (ENumeric 1)))\n" + " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n" + " (SExpression (EAssignment (EVariable itr) ++ post))\n" - + " (SDeclBlock (SDeclaration int tmp (EVariable a)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) tmp (EVariable a)))\n" + " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n" + " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n" + " (SReturn (EVariable b)))", @@ -649,7 +650,7 @@ public class NodeToStringTests extends ESTestCase { public void testSEach() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int l (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) l (ENumeric 0)))\n" + " (SEach String s (EListInit (EString 'cat') (EString 'dog') (EString 'chicken')) (SBlock " + "(SExpression (EAssignment (EVariable l) += (PCallInvoke (EVariable s) length)))))\n" + " (SReturn (EVariable l)))", @@ -660,9 +661,9 @@ public class NodeToStringTests extends ESTestCase { + "return l"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int l (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) l (ENumeric 0)))\n" + " (SEach String s (EListInit (EString 'cat') (EString 'dog') (EString 'chicken')) (SBlock\n" - + " (SDeclBlock (SDeclaration String s2 (EBinary (EString 'dire ') + (EVariable s))))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [String]) s2 (EBinary (EString 'dire ') + (EVariable s))))\n" + " (SExpression (EAssignment (EVariable l) += (PCallInvoke (EVariable s2) length)))))\n" + " (SReturn (EVariable l)))", "int l = 0;\n" @@ -676,9 +677,9 @@ public class NodeToStringTests extends ESTestCase { public void testSFor() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int sum (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) sum (ENumeric 0)))\n" + " (SFor\n" - + " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" + " (EComp (EVariable i) < (ENumeric 1000))\n" + " (EAssignment (EVariable i) ++ post)\n" + " (SBlock (SExpression (EAssignment (EVariable sum) += (EVariable i)))))\n" @@ -690,13 +691,13 @@ public class NodeToStringTests extends ESTestCase { + "return sum"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int sum (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) sum (ENumeric 0)))\n" + " (SFor\n" - + " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" + " (EComp (EVariable i) < (ENumeric 1000))\n" + " (EAssignment (EVariable i) ++ post)\n" + " (SBlock (SFor\n" - + " (SDeclBlock (SDeclaration int j (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) j (ENumeric 0)))\n" + " (EComp (EVariable j) < (ENumeric 1000))\n" + " (EAssignment (EVariable j) ++ post)\n" + " (SBlock (SExpression (EAssignment (EVariable sum) += (EBinary (EVariable i) * (EVariable j))))))))\n" @@ -740,7 +741,7 @@ public class NodeToStringTests extends ESTestCase { + "}"); assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" + " (SIfElse (PField (EVariable param) a)\n" + " (SBlock (SIfElse (PField (EVariable param) b)\n" + " (SBlock (SReturn (EBoolean true)))\n" @@ -789,7 +790,7 @@ public class NodeToStringTests extends ESTestCase { public void testSWhile() { assertToString( "(SClass\n" - + " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 0)))\n" + " (SWhile (EComp (EVariable i) < (ENumeric 10)) (SBlock (SExpression (EAssignment (EVariable i) ++ post))))\n" + " (SReturn (EVariable i)))", "int i = 0;\n" @@ -822,7 +823,7 @@ public class NodeToStringTests extends ESTestCase { "(SClass\n" + " (SFunction def a (Args (Pair int i) (Pair int j))\n" + " (SIf (EComp (EVariable i) < (EVariable j)) (SBlock (SReturn (EBoolean true))))\n" - + " (SDeclBlock (SDeclaration int k (EBinary (EVariable i) + (EVariable j))))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) k (EBinary (EVariable i) + (EVariable j))))\n" + " (SReturn (EVariable k)))\n" + " (SReturn (EBoolean true)))", "def a(int i, int j) {\n" @@ -860,7 +861,7 @@ public class NodeToStringTests extends ESTestCase { + "}"); assertToString( "(SClass (STry (SBlock\n" - + " (SDeclBlock (SDeclaration int i (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 1)))\n" + " (SReturn (ENumeric 1)))\n" + " (SCatch Exception e (SBlock (SReturn (ENumeric 2))))))", "try {\n" @@ -872,7 +873,7 @@ public class NodeToStringTests extends ESTestCase { assertToString( "(SClass (STry (SBlock (SReturn (ENumeric 1)))\n" + " (SCatch Exception e (SBlock\n" - + " (SDeclBlock (SDeclaration int i (ENumeric 1)))\n" + + " (SDeclBlock (SDeclaration (DUnresolvedType [int]) i (ENumeric 1)))\n" + " (SReturn (ENumeric 2))))))", "try {\n" + " return 1\n"