From 8d6dc7596def77e0f7f746ac1741271b78c366d4 Mon Sep 17 00:00:00 2001 From: Mohan Date: Wed, 29 Apr 2020 12:44:19 +0530 Subject: [PATCH 1/5] Add negative testcases for table functions --- .../langlib/test/LangLibTableTest.java | 21 ++++++++---- .../test-src/tablelib_test_negative.bal | 34 +++++++++++++++++++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java index 09fce16f5979..b8c9d1896641 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTableTest.java @@ -154,18 +154,27 @@ public void removeWithInvalidKey() { @Test public void testCompilerNegativeCases() { - validateError(negativeResult, 0, "incompatible types: expected 'table " + + assertEquals(negativeResult.getErrorCount(), 9); + int index = 0; + validateError(negativeResult, index++, "incompatible types: expected 'table " + "key(name)', found 'table key'", 66, 36); - validateError(negativeResult, 1, "incompatible types: expected 'Employee', " + + validateError(negativeResult, index++, "incompatible types: expected 'Employee', " + "found 'Person'", 66, 47); - validateError(negativeResult, 2, "incompatible types: expected " + + validateError(negativeResult, index++, "incompatible types: expected " + "'object { public function next () returns (record {| Employee value; |}?); }', found " + "'object { public function next () returns (record {| Person value; |}?); }'", 75, 92); - validateError(negativeResult, 3, "incompatible types: expected 'table<(any|error)> " + + validateError(negativeResult, index++, "incompatible types: expected 'table<(any|error)> " + "key', found 'table key(name)'", 82, 12); - validateError(negativeResult, 4, "incompatible types: expected 'table<(any|error)> " + + validateError(negativeResult, index++, "incompatible types: expected 'table<(any|error)> " + "key', found 'table'", 94, 12); - assertEquals(negativeResult.getErrorCount(), 5); + validateError(negativeResult, index++, "incompatible types: expected 'table<(any|error)> " + + "key', found 'table'", 105, 21); + validateError(negativeResult, index++, "incompatible types: expected 'table<(any|error)> " + + "key', found 'table'", 117, 28); + validateError(negativeResult, index++, "incompatible types: expected 'table<(any|error)> " + + "key', found 'table'", 126, 30); + validateError(negativeResult, index++, "incompatible types: expected 'table<(any|error)> " + + "key', found 'table'", 127, 30); } } diff --git a/langlib/langlib-test/src/test/resources/test-src/tablelib_test_negative.bal b/langlib/langlib-test/src/test/resources/test-src/tablelib_test_negative.bal index c0461bbc3361..cca43da28046 100644 --- a/langlib/langlib-test/src/test/resources/test-src/tablelib_test_negative.bal +++ b/langlib/langlib-test/src/test/resources/test-src/tablelib_test_negative.bal @@ -93,3 +93,37 @@ function getKeysFromKeyLessTbl() returns boolean { ]; return keyless.keys().length() == 0; } + +function getValueFromTable() { + table tab = table [ + { name: "Chiran", age: 33 }, + { name: "Mohan", age: 37 }, + { name: "Gima", age: 38 }, + { name: "Granier", age: 34 } + ]; + + Person person = tab.get("Chiran"); + int value = person["age"]; +} + +function removeWithInvalidKey() returns boolean { + table tab = table [ + { name: "Chiran", age: 33 }, + { name: "Mohan", age: 37 }, + { name: "Gima", age: 38 }, + { name: "Granier", age: 34 } + ]; + + Person removedPerson = tab.remove("Chiran"); + return removedPerson.name == "Chiran"; +} + +function removeIfHasKey() returns boolean { + table tbl = table [{ name: "Chiran", age: 33 }, + { name: "Mohan", age: 37 }, + { name: "Gima", age: 38 }, + { name: "Granier", age: 34 }]; + Person? removedPerson1 = tbl.removeIfHasKey("AAA"); + Person? removedPerson2 = tbl.removeIfHasKey("Chiran"); + return removedPerson1 == () && removedPerson2?.name == "Chiran"; +} From a27f2e0e62201be1d0bd571af5c3613ec2b400d9 Mon Sep 17 00:00:00 2001 From: Chiran Date: Wed, 29 Apr 2020 15:39:28 +0530 Subject: [PATCH 2/5] Add table function introduced version as a comment --- .../ballerinalang/langlib/table/Filter.java | 1 + .../ballerinalang/langlib/table/Foreach.java | 1 + .../org/ballerinalang/langlib/table/Get.java | 1 + .../langlib/table/GetIterator.java | 1 + .../ballerinalang/langlib/table/GetKeys.java | 2 + .../ballerinalang/langlib/table/HasKey.java | 2 + .../ballerinalang/langlib/table/Length.java | 1 + .../org/ballerinalang/langlib/table/Map.java | 1 + .../org/ballerinalang/langlib/table/Next.java | 1 + .../ballerinalang/langlib/table/NextKey.java | 2 + .../ballerinalang/langlib/table/Reduce.java | 1 + .../ballerinalang/langlib/table/Remove.java | 1 + .../langlib/table/RemoveAll.java | 1 + .../langlib/table/RemoveIfHasKey.java | 1 + .../ballerinalang/langlib/table/ToArray.java | 40 ++----------------- 15 files changed, 20 insertions(+), 37 deletions(-) diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Filter.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Filter.java index 95fe00455c8a..3f3d2a1ccd0b 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Filter.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Filter.java @@ -34,6 +34,7 @@ /** * Native implementation of lang.table:filter(table<Type>, function). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "filter", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Foreach.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Foreach.java index bb7c2ccd203f..e984a76d1a36 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Foreach.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Foreach.java @@ -31,6 +31,7 @@ /** * Native implementation of lang.table:forEach(table<Type>, function). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "forEach", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Get.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Get.java index dda23a28bfa3..5d1ca9c8aafe 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Get.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Get.java @@ -28,6 +28,7 @@ /** * Native implementation of lang.table:get(table<Type>, KeyType). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "get", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetIterator.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetIterator.java index 39d7413894ec..5cf3420cde7d 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetIterator.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetIterator.java @@ -29,6 +29,7 @@ /** * Native implementation of lang.table:iterator(table<Type>). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "iterator", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetKeys.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetKeys.java index 6f719458753c..b7d8e46da6fc 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetKeys.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/GetKeys.java @@ -34,6 +34,8 @@ /** * Extern function to get key arrays from the table. * ballerina.model.table:keys() + * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/HasKey.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/HasKey.java index 2eafd1c117a2..bd03c82a1cea 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/HasKey.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/HasKey.java @@ -28,6 +28,8 @@ /** * Extern function to check existence of key. * ballerina.model.table:hasKey(KeyType) + * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "hasKey", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Length.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Length.java index e5195aa08e26..04d6238c2ca3 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Length.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Length.java @@ -28,6 +28,7 @@ /** * Native implementation of lang.table:length(map). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "length", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Map.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Map.java index 4a7ff6102db3..0a1a340d803e 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Map.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Map.java @@ -36,6 +36,7 @@ /** * Native implementation of lang.table:map(table<Type>, function). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "map", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Next.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Next.java index afa1764d3681..629879f6bf4c 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Next.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Next.java @@ -33,6 +33,7 @@ /** * Native implementation of lang.table.TableIterator:next(). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "next", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/NextKey.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/NextKey.java index fd8af5268eb1..3a70f90c11b4 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/NextKey.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/NextKey.java @@ -28,6 +28,8 @@ /** * Extern function to get next key from the table. * ballerina.model.table:nextKey() + * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Reduce.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Reduce.java index 831e313df81e..06820785ba68 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Reduce.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Reduce.java @@ -33,6 +33,7 @@ /** * Native implementation of lang.table:reduce(table<Type>, function). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "reduce", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Remove.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Remove.java index 3fa0eca75948..08a3853cad15 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Remove.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/Remove.java @@ -28,6 +28,7 @@ /** * Native implementation of lang.table:remove(table<Type>, KeyType). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "remove", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveAll.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveAll.java index 2d254b900696..5e09b9516f4c 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveAll.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveAll.java @@ -28,6 +28,7 @@ /** * Native implementation of lang.table:removeAll(table<Type>). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "removeAll", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveIfHasKey.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveIfHasKey.java index 709f84d4a4d0..8dd2dcf39b33 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveIfHasKey.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/RemoveIfHasKey.java @@ -28,6 +28,7 @@ /** * Native implementation of lang.table:removeIfHasKey(table<Type>, KeyType). * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", functionName = "removeIfHasKey", diff --git a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/ToArray.java b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/ToArray.java index 5c56cc3d5a7c..7be64f2b4dc3 100644 --- a/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/ToArray.java +++ b/langlib/lang.table/src/main/java/org/ballerinalang/langlib/table/ToArray.java @@ -22,7 +22,6 @@ import org.ballerinalang.jvm.types.BArrayType; import org.ballerinalang.jvm.types.BTableType; import org.ballerinalang.jvm.types.BType; -import org.ballerinalang.jvm.types.TypeTags; import org.ballerinalang.jvm.values.ArrayValue; import org.ballerinalang.jvm.values.ArrayValueImpl; import org.ballerinalang.jvm.values.TableValueImpl; @@ -36,6 +35,7 @@ /** * Function for returning the values of the table as an array. T[] vals = tbl.toArray(); * + * @since 1.3.0 */ @BallerinaFunction( orgName = "ballerina", packageName = "lang.table", @@ -50,41 +50,7 @@ public static ArrayValue toArray(Strand strand, TableValueImpl tbl) { BType constrainedType = ((BTableType) tbl.getType()).getConstrainedType(); Collection values = tbl.values(); - int size = values.size(); - int i = 0; - switch (constrainedType.getTag()) { - case TypeTags.INT_TAG: - long[] intArr = new long[size]; - for (Object val : values) { - intArr[i++] = (Long) val; - } - return new ArrayValueImpl(intArr); - case TypeTags.FLOAT_TAG: - double[] floatArr = new double[size]; - for (Object val : values) { - floatArr[i++] = (Double) val; - } - return new ArrayValueImpl(floatArr); - case TypeTags.BYTE_TAG: - byte[] byteArr = new byte[size]; - for (Object val : values) { - byteArr[i++] = ((Integer) val).byteValue(); - } - return new ArrayValueImpl(byteArr); - case TypeTags.BOOLEAN_TAG: - boolean[] booleanArr = new boolean[size]; - for (Object val : values) { - booleanArr[i++] = (Boolean) val; - } - return new ArrayValueImpl(booleanArr); - case TypeTags.STRING_TAG: - String[] stringArr = new String[size]; - for (Object val : values) { - stringArr[i++] = (String) val; - } - return new ArrayValueImpl(stringArr); - default: - return new ArrayValueImpl(values.toArray(), new BArrayType(constrainedType)); - } + //Basic constrain types not applicable for table type + return new ArrayValueImpl(values.toArray(), new BArrayType(constrainedType)); } } From 398df1977ee7898d384e05fc0aa82636b1b3bd98 Mon Sep 17 00:00:00 2001 From: Mohan Date: Wed, 29 Apr 2020 16:19:47 +0530 Subject: [PATCH 3/5] Refactor IndexBasedAccess node as per review feedback --- .../jvm/values/TableValueImpl.java | 1 - .../tree/expressions/IndexBasedAccessNode.java | 2 -- .../compiler/desugar/ClosureDesugar.java | 9 +++++++++ .../compiler/desugar/ConstantPropagation.java | 1 - .../ballerinalang/compiler/desugar/Desugar.java | 17 ++++++++++++----- .../compiler/parser/BLangPackageBuilder.java | 2 +- .../compiler/parser/NodeCloner.java | 1 - .../semantics/analyzer/CodeAnalyzer.java | 1 - .../semantics/analyzer/DataflowAnalyzer.java | 1 - .../semantics/analyzer/TaintAnalyzer.java | 6 ++++++ .../semantics/analyzer/TypeChecker.java | 9 ++++++--- .../tree/expressions/BLangIndexBasedAccess.java | 12 +----------- 12 files changed, 35 insertions(+), 27 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/org/ballerinalang/jvm/values/TableValueImpl.java b/bvm/ballerina-runtime/src/main/java/org/ballerinalang/jvm/values/TableValueImpl.java index 4672a5d05576..8bdaa6e5a208 100644 --- a/bvm/ballerina-runtime/src/main/java/org/ballerinalang/jvm/values/TableValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/org/ballerinalang/jvm/values/TableValueImpl.java @@ -103,7 +103,6 @@ private void addData(ArrayValue data) { } } - @Override public IteratorValue getIterator() { return new TableIterator(entries.values().iterator()); diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/expressions/IndexBasedAccessNode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/expressions/IndexBasedAccessNode.java index e056acb63cfb..0c916834bf78 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/expressions/IndexBasedAccessNode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/expressions/IndexBasedAccessNode.java @@ -27,6 +27,4 @@ public interface IndexBasedAccessNode extends VariableReferenceNode { ExpressionNode getExpression(); ExpressionNode getIndex(); - - TableMultiKeyExpressionNode getMultiKeyExpr(); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java index aa4c035c02bb..0c3191f5311f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java @@ -81,6 +81,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangStringTemplateLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableMultiKeyExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTernaryExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTrapExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTupleVarRef; @@ -747,6 +748,14 @@ public void visit(BLangInvocation iExpr) { result = iExpr; } + @Override + public void visit(BLangTableMultiKeyExpr tableMultiKeyExpr) { + List exprList = new ArrayList<>(); + tableMultiKeyExpr.multiKeyIndexExprs.forEach(expression -> exprList.add(rewriteExpr(expression))); + tableMultiKeyExpr.multiKeyIndexExprs = exprList; + result = tableMultiKeyExpr; + } + public void visit(BLangTypeInit typeInitExpr) { typeInitExpr.initInvocation = rewriteExpr(typeInitExpr.initInvocation); result = typeInitExpr; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java index 4baf4a9b1ff4..ee479277f652 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java @@ -509,7 +509,6 @@ public void visit(BLangFieldBasedAccess fieldAccessExpr) { public void visit(BLangIndexBasedAccess indexAccessExpr) { indexAccessExpr.expr = rewrite(indexAccessExpr.expr); indexAccessExpr.indexExpr = rewrite(indexAccessExpr.indexExpr); - indexAccessExpr.multiKeyExpr = rewrite(indexAccessExpr.multiKeyExpr); result = indexAccessExpr; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java index 8e63399d2072..6b0c822ddee7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java @@ -153,6 +153,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangStringTemplateLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableMultiKeyExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTernaryExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTrapExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTupleVarRef; @@ -3566,12 +3567,12 @@ public void visit(BLangIndexBasedAccess indexAccessExpr) { targetVarRef = new BLangXMLAccessExpr(indexAccessExpr.pos, indexAccessExpr.expr, indexAccessExpr.indexExpr); } else if (varRefType.tag == TypeTags.TABLE) { - if (targetVarRef.multiKeyExpr != null) { - BLangTupleLiteral listConstructorExpr = - new BLangTupleLiteral(); - listConstructorExpr.exprs = indexAccessExpr.multiKeyExpr.multiKeyIndexExprs; + if (targetVarRef.indexExpr.getKind() == NodeKind.TABLE_MULTI_KEY) { + BLangTupleLiteral listConstructorExpr = new BLangTupleLiteral(); + listConstructorExpr.exprs = ((BLangTableMultiKeyExpr) indexAccessExpr.indexExpr).multiKeyIndexExprs; List memberTypes = new ArrayList<>(); - indexAccessExpr.multiKeyExpr.multiKeyIndexExprs.forEach(expression -> memberTypes.add(expression.type)); + ((BLangTableMultiKeyExpr) indexAccessExpr.indexExpr).multiKeyIndexExprs. + forEach(expression -> memberTypes.add(expression.type)); listConstructorExpr.type = new BTupleType(memberTypes); indexAccessExpr.indexExpr = listConstructorExpr; } @@ -3584,6 +3585,12 @@ public void visit(BLangIndexBasedAccess indexAccessExpr) { result = targetVarRef; } + @Override + public void visit(BLangTableMultiKeyExpr tableMultiKeyExpr) { + rewriteExprs(tableMultiKeyExpr.multiKeyIndexExprs); + result = tableMultiKeyExpr; + } + @Override public void visit(BLangInvocation iExpr) { BLangInvocation genIExpr = iExpr; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangPackageBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangPackageBuilder.java index e2eff01a2e3f..1d47e8740301 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangPackageBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangPackageBuilder.java @@ -1800,7 +1800,7 @@ void createIndexBasedAccessNode(DiagnosticPos pos, Set ws) { indexBasedAccess.pos = pos; indexBasedAccess.addWS(ws); if (tableMultiKeyExpressionNodeStack.size() == 1) { - indexBasedAccess.multiKeyExpr = (BLangTableMultiKeyExpr) tableMultiKeyExpressionNodeStack.pop(); + indexBasedAccess.indexExpr = (BLangTableMultiKeyExpr) tableMultiKeyExpressionNodeStack.pop(); } else { indexBasedAccess.indexExpr = (BLangExpression) exprNodeStack.pop(); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java index f65f5f64be6b..59eaef0b4502 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java @@ -307,7 +307,6 @@ private void cloneBLangAccessExpression(BLangAccessExpression source, BLangAcces private void cloneBLangIndexBasedAccess(BLangIndexBasedAccess source, BLangIndexBasedAccess clone) { clone.indexExpr = clone(source.indexExpr); - clone.multiKeyExpr = clone(source.multiKeyExpr); cloneBLangAccessExpression(source, clone); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 44a63e1933ae..735b7ffe738a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1996,7 +1996,6 @@ public void visit(BLangFieldBasedAccess fieldAccessExpr) { public void visit(BLangIndexBasedAccess indexAccessExpr) { analyzeExpr(indexAccessExpr.indexExpr); analyzeExpr(indexAccessExpr.expr); - analyzeExpr(indexAccessExpr.multiKeyExpr); } public void visit(BLangTableMultiKeyExpr tableMultiKeyExpr) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java index 716a2acf2b2f..d2c872ace6f7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java @@ -749,7 +749,6 @@ public void visit(BLangFieldBasedAccess fieldAccessExpr) { public void visit(BLangIndexBasedAccess indexAccessExpr) { analyzeNode(indexAccessExpr.expr, env); analyzeNode(indexAccessExpr.indexExpr, env); - analyzeNode(indexAccessExpr.multiKeyExpr, env); } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TaintAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TaintAnalyzer.java index 0ac35fa10552..837577d57637 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TaintAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TaintAnalyzer.java @@ -91,6 +91,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangStringTemplateLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableMultiKeyExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTernaryExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTrapExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeConversionExpr; @@ -1032,6 +1033,11 @@ public void visit(BLangIndexBasedAccess indexAccessExpr) { indexAccessExpr.expr.accept(this); } + @Override + public void visit(BLangTableMultiKeyExpr tableMultiKeyExpr) { + analyzeExprList(tableMultiKeyExpr.multiKeyIndexExprs); + } + @Override public void visit(BLangInvocation invocationExpr) { // handle error constructor invocation diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 6b4ac0ee06ca..0df11ca94f6a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -117,6 +117,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangStringTemplateLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableMultiKeyExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTernaryExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTrapExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTupleVarRef; @@ -1983,7 +1984,8 @@ public void visit(BLangIndexBasedAccess indexBasedAccessExpr) { indexBasedAccessExpr.compoundAssignmentLhsVar; checkExpr(indexBasedAccessExpr.expr, this.env, symTable.noType); - if (indexBasedAccessExpr.multiKeyExpr != null && indexBasedAccessExpr.expr.type.tag != TypeTags.TABLE) { + if (indexBasedAccessExpr.indexExpr.getKind() == NodeKind.TABLE_MULTI_KEY && + indexBasedAccessExpr.expr.type.tag != TypeTags.TABLE) { dlog.error(indexBasedAccessExpr.pos, DiagnosticCode.MULTI_KEY_MEMBER_ACCESS_NOT_SUPPORTED, indexBasedAccessExpr.expr.type); resultType = symTable.semanticError; @@ -5276,7 +5278,7 @@ private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr) { } } - if (indexExpr != null) { + if (indexExpr.getKind() != NodeKind.TABLE_MULTI_KEY) { checkExpr(indexExpr, this.env, keyTypeConstraint); if (indexExpr.type == symTable.semanticError) { dlog.error(indexBasedAccessExpr.pos, DiagnosticCode.INVALID_KEY_CONSTRAINT_PROVIDED_FOR_ACCESS, @@ -5284,7 +5286,8 @@ private BType checkIndexAccessExpr(BLangIndexBasedAccess indexBasedAccessExpr) { return symTable.semanticError; } } else { - List multiKeyExpressionList = indexBasedAccessExpr.multiKeyExpr.multiKeyIndexExprs; + List multiKeyExpressionList = ((BLangTableMultiKeyExpr) + indexBasedAccessExpr.indexExpr).multiKeyIndexExprs; List keyConstraintTypes = ((BTupleType) keyTypeConstraint).tupleTypes; if (keyConstraintTypes.size() != multiKeyExpressionList.size()) { dlog.error(indexBasedAccessExpr.pos, DiagnosticCode.INVALID_KEY_CONSTRAINT_PROVIDED_FOR_ACCESS, diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangIndexBasedAccess.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangIndexBasedAccess.java index 4aedf350bdd5..b68a5f7437eb 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangIndexBasedAccess.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangIndexBasedAccess.java @@ -32,7 +32,6 @@ public class BLangIndexBasedAccess extends BLangAccessExpression implements IndexBasedAccessNode { public BLangExpression indexExpr; - public BLangTableMultiKeyExpr multiKeyExpr; // Only used at Desugar and after. public boolean isStoreOnCreation = false; @@ -49,16 +48,7 @@ public BLangExpression getIndex() { @Override public String toString() { - if (indexExpr != null) { - return String.valueOf(expr) + "[" + String.valueOf(indexExpr) + "]"; - } else { - return String.valueOf(expr) + "[" + multiKeyExpr.toString(); - } - } - - @Override - public BLangTableMultiKeyExpr getMultiKeyExpr() { - return this.multiKeyExpr; + return String.valueOf(expr) + "[" + String.valueOf(indexExpr) + "]"; } @Override From 9439a3dcf4b000902323e8228b2c45d0cac121fa Mon Sep 17 00:00:00 2001 From: Mohan Date: Wed, 29 Apr 2020 16:28:31 +0530 Subject: [PATCH 4/5] Add modifications as per review comments --- .../org/ballerinalang/model/tree/types/TableTypeNode.java | 4 ++-- .../main/java/org/ballerinalang/model/types/TableType.java | 2 +- .../org/ballerinalang/util/diagnostic/DiagnosticCode.java | 2 +- .../compiler/tree/expressions/BLangTableConstructorExpr.java | 3 +-- .../compiler/tree/expressions/BLangTableMultiKeyExpr.java | 2 ++ .../ballerinalang/compiler/tree/types/BLangTableTypeNode.java | 2 ++ .../ballerina-lang/src/main/resources/compiler.properties | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/types/TableTypeNode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/types/TableTypeNode.java index c7ba653cdf9f..d010396a4215 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/types/TableTypeNode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/types/TableTypeNode.java @@ -21,9 +21,9 @@ import org.ballerinalang.model.tree.TableKeyTypeConstraintNode; /** - * table<Person> key(...);. + * {@code TableTypeNode} represents a table type node in Ballerina. * - * @since 1.2.0 + * @since 1.3.0 */ public interface TableTypeNode extends TypeNode { diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/TableType.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/TableType.java index e375f4aac005..a34e2fae2bf8 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/TableType.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/types/TableType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticCode.java index 976642746f97..7200ecd057c5 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticCode.java @@ -406,7 +406,7 @@ public enum DiagnosticCode { MISSING_REQUIRED_METHOD_NEXT("missing.required.method.next"), // Table related codes - TABLE_CONSTRAINT_INVALID_SUBTYPE("invalid.stream.constraint.subtype"), + TABLE_CONSTRAINT_INVALID_SUBTYPE("invalid.table.constraint.subtype"), TABLE_KEY_SPECIFIER_MISMATCH("table.key.specifier.mismatch"), KEY_SPECIFIER_SIZE_MISMATCH_WITH_KEY_CONSTRAINT("key.specifier.size.mismatch.with.key.constraint"), KEY_SPECIFIER_MISMATCH_WITH_KEY_CONSTRAINT("key.specifier.mismatch.with.key.constraint"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableConstructorExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableConstructorExpr.java index a4c64d69c8ce..8fc97cb316b1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableConstructorExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableConstructorExpr.java @@ -28,9 +28,8 @@ import java.util.List; /** - * BLangTableConstructorExpr class. + * Implementation of Table constructor expression. * - * @see BLangTableConstructorExpr * @since 1.3.0 */ public class BLangTableConstructorExpr extends BLangExpression implements TableConstructorExprNode { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableMultiKeyExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableMultiKeyExpr.java index 0e2f25471b42..1a9581b2b863 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableMultiKeyExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangTableMultiKeyExpr.java @@ -25,6 +25,8 @@ import java.util.List; /** + * Represents an expression which can hold expressions related to table member access. + * * @since 1.3.0 */ public class BLangTableMultiKeyExpr extends BLangAccessExpression implements TableMultiKeyExpressionNode { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangTableTypeNode.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangTableTypeNode.java index c96ab68812ea..c0d11abd80d8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangTableTypeNode.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/types/BLangTableTypeNode.java @@ -27,6 +27,8 @@ import org.wso2.ballerinalang.compiler.tree.BLangTableKeyTypeConstraint; /** + * {@code BLangTableTypeNode} represents a table type node in Ballerina. + * * @since 1.3.0 */ public class BLangTableTypeNode extends BLangType implements TableTypeNode { diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 649897a2c97c..5c0304748b9d 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -1009,7 +1009,7 @@ error.error.type.expected = \ error.missing.required.method.next = \ ''{0}'' must implement ''public function next() returns {1}''. -error.invalid.stream.constraint.subtype = \ +error.invalid.table.constraint.subtype = \ invalid constraint type. expected subtype of ''map'' but ''{0}'' error.table.key.specifier.mismatch = \ From 76842f7d324f9939e98bce6dc1cefa15fe0eb6ed Mon Sep 17 00:00:00 2001 From: Mohan Date: Wed, 29 Apr 2020 16:36:28 +0530 Subject: [PATCH 5/5] Remove invalida todo flag --- .../wso2/ballerinalang/compiler/semantics/analyzer/Types.java | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java index 53a98cabdbb1..f40f901599c9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java @@ -547,7 +547,6 @@ private boolean isAssignable(BType source, BType target, Set unresolve unresolvedTypes); } - //TODO Need to check the key specifier if (targetTag == TypeTags.TABLE && sourceTag == TypeTags.TABLE) { return isAssignableTableType((BTableType) source, (BTableType) target); }