From 995243c63d760ae6f82630a3d272a8e9801cacbf Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 17 Jul 2024 16:07:10 -0700 Subject: [PATCH 01/33] Do not override the container if it's missing from policy config PiperOrigin-RevId: 653392239 --- policy/src/main/java/dev/cel/policy/CelPolicyConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java b/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java index c5acc43f5..d3786d512 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java @@ -127,6 +127,10 @@ public Cel extend(Cel cel, CelOptions celOptions) throws CelPolicyValidationExce .map(f -> f.toCelFunctionDecl(celTypeProvider)) .collect(toImmutableList())); + if (!container().isEmpty()) { + celBuilder.setContainer(container()); + } + addAllExtensions(celBuilder, celOptions); return celBuilder.build(); From 882f6318cac908e103ab4b3fdf17409c4b929f7e Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 18 Jul 2024 22:16:24 -0700 Subject: [PATCH 02/33] Add option to specify folding designated custom functions only PiperOrigin-RevId: 653874748 --- .../main/java/dev/cel/extensions/BUILD.bazel | 1 + .../cel/extensions/CelEncoderExtensions.java | 56 ++++++++++++++----- .../dev/cel/extensions/CelExtensions.java | 24 ++++++++ .../dev/cel/extensions/CelMathExtensions.java | 6 +- .../dev/cel/extensions/CelSetsExtensions.java | 4 ++ .../cel/extensions/CelStringExtensions.java | 4 ++ .../dev/cel/extensions/CelExtensionsTest.java | 24 +++++++- .../dev/cel/optimizer/optimizers/BUILD.bazel | 21 ++++++- .../optimizers/ConstantFoldingOptimizer.java | 54 +++++++++++++++++- .../optimizers/DefaultOptimizerConstants.java | 50 +++++++++++++++++ .../optimizers/SubexpressionOptimizer.java | 15 +---- .../ConstantFoldingOptimizerTest.java | 46 ++++++++++++++- 12 files changed, 269 insertions(+), 36 deletions(-) create mode 100644 optimizer/src/main/java/dev/cel/optimizer/optimizers/DefaultOptimizerConstants.java diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel index da8aba9a0..9cf66cf1e 100644 --- a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel @@ -102,6 +102,7 @@ java_library( "//compiler:compiler_builder", "//runtime", "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java index 46ad08262..bc882aa0e 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java @@ -14,6 +14,7 @@ package dev.cel.extensions; +import com.google.common.collect.ImmutableSet; import com.google.errorprone.annotations.Immutable; import com.google.protobuf.ByteString; import dev.cel.checker.CelCheckerBuilder; @@ -35,31 +36,58 @@ public class CelEncoderExtensions implements CelCompilerLibrary, CelRuntimeLibra private static final Decoder BASE64_DECODER = Base64.getDecoder(); - @Override - public void setCheckerOptions(CelCheckerBuilder checkerBuilder) { - checkerBuilder.addFunctionDeclarations( + private final ImmutableSet functions; + + enum Function { + DECODE( CelFunctionDecl.newFunctionDeclaration( "base64.decode", CelOverloadDecl.newGlobalOverload( "base64_decode_string", SimpleType.BYTES, SimpleType.STRING)), + ImmutableSet.of( + CelRuntime.CelFunctionBinding.from( + "base64_decode_string", + String.class, + str -> ByteString.copyFrom(BASE64_DECODER.decode(str))))), + ENCODE( CelFunctionDecl.newFunctionDeclaration( "base64.encode", CelOverloadDecl.newGlobalOverload( - "base64_encode_bytes", SimpleType.STRING, SimpleType.BYTES))); + "base64_encode_bytes", SimpleType.STRING, SimpleType.BYTES)), + ImmutableSet.of( + CelRuntime.CelFunctionBinding.from( + "base64_encode_bytes", + ByteString.class, + bytes -> BASE64_ENCODER.encodeToString(bytes.toByteArray())))), + ; + + private final CelFunctionDecl functionDecl; + private final ImmutableSet functionBindings; + + String getFunction() { + return functionDecl.name(); + } + + Function( + CelFunctionDecl functionDecl, + ImmutableSet functionBindings) { + this.functionDecl = functionDecl; + this.functionBindings = functionBindings; + } + } + + @Override + public void setCheckerOptions(CelCheckerBuilder checkerBuilder) { + functions.forEach(function -> checkerBuilder.addFunctionDeclarations(function.functionDecl)); } @SuppressWarnings("Immutable") // Instances of java.util.Base64 are immutable @Override public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) { - runtimeBuilder.addFunctionBindings( - CelRuntime.CelFunctionBinding.from( - "base64_decode_string", - String.class, - str -> ByteString.copyFrom(BASE64_DECODER.decode(str))), - CelRuntime.CelFunctionBinding.from( - "base64_encode_bytes", - ByteString.class, - bytes -> BASE64_ENCODER.encodeToString(bytes.toByteArray()))); + functions.forEach(function -> runtimeBuilder.addFunctionBindings(function.functionBindings)); } -} + public CelEncoderExtensions() { + this.functions = ImmutableSet.copyOf(Function.values()); + } +} diff --git a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java index 5515d6a89..662246283 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java @@ -14,7 +14,11 @@ package dev.cel.extensions; +import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static java.util.Arrays.stream; + import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Streams; import dev.cel.common.CelOptions; import java.util.Set; @@ -206,5 +210,25 @@ public static CelSetsExtensions sets(Set functions) return new CelSetsExtensions(functions); } + /** + * Retrieves all function names used by every extension libraries. + * + *

Note: Certain extensions such as {@link CelProtoExtensions} and {@link + * CelBindingsExtensions} are implemented via macros, not functions, and those are not included + * here. + */ + public static ImmutableSet getAllFunctionNames() { + return Streams.concat( + stream(CelMathExtensions.Function.values()) + .map(CelMathExtensions.Function::getFunction), + stream(CelStringExtensions.Function.values()) + .map(CelStringExtensions.Function::getFunction), + stream(CelSetsExtensions.Function.values()) + .map(CelSetsExtensions.Function::getFunction), + stream(CelEncoderExtensions.Function.values()) + .map(CelEncoderExtensions.Function::getFunction)) + .collect(toImmutableSet()); + } + private CelExtensions() {} } diff --git a/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java index c6423a05a..ef1877b4c 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java @@ -104,7 +104,7 @@ final class CelMathExtensions implements CelCompilerLibrary, CelRuntimeLibrary { return builder.buildOrThrow(); } - public enum Function { + enum Function { MAX( CelFunctionDecl.newFunctionDeclaration( MATH_MAX_FUNCTION, @@ -341,6 +341,10 @@ public enum Function { private final ImmutableSet functionBindingsULongSigned; private final ImmutableSet functionBindingsULongUnsigned; + String getFunction() { + return functionDecl.name(); + } + Function( CelFunctionDecl functionDecl, ImmutableSet functionBindings, diff --git a/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java index 10fcbdd0c..e410edade 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java @@ -112,6 +112,10 @@ public enum Function { private final CelFunctionDecl functionDecl; private final ImmutableSet functionBindings; + String getFunction() { + return functionDecl.name(); + } + Function(CelFunctionDecl functionDecl, CelRuntime.CelFunctionBinding... functionBindings) { this.functionDecl = functionDecl; this.functionBindings = ImmutableSet.copyOf(functionBindings); diff --git a/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java index 69fbad8d1..473722b26 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java @@ -229,6 +229,10 @@ public enum Function { private final CelFunctionDecl functionDecl; private final ImmutableSet functionBindings; + String getFunction() { + return functionDecl.name(); + } + Function(CelFunctionDecl functionDecl, CelRuntime.CelFunctionBinding... functionBindings) { this.functionDecl = functionDecl; this.functionBindings = ImmutableSet.copyOf(functionBindings); diff --git a/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java index 0b2e7b2cd..d7b75f8dd 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java @@ -138,5 +138,27 @@ public void addEncoderExtension_success() throws Exception { assertThat(evaluatedResult).isTrue(); } -} + @Test + public void getAllFunctionNames() { + assertThat(CelExtensions.getAllFunctionNames()) + .containsExactly( + "math.@max", + "math.@min", + "charAt", + "indexOf", + "join", + "lastIndexOf", + "lowerAscii", + "replace", + "split", + "substring", + "trim", + "upperAscii", + "sets.contains", + "sets.equivalent", + "sets.intersects", + "base64.decode", + "base64.encode"); + } +} diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel b/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel index 2b0cc563b..9b679d9bd 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/BUILD.bazel @@ -14,6 +14,7 @@ java_library( tags = [ ], deps = [ + ":default_optimizer_constants", "//:auto_value", "//bundle:cel", "//common", @@ -29,6 +30,7 @@ java_library( "//optimizer:optimization_exception", "//parser:operator", "//runtime", + "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) @@ -41,9 +43,9 @@ java_library( tags = [ ], deps = [ + ":default_optimizer_constants", "//:auto_value", "//bundle:cel", - "//checker:checker_legacy_environment", "//common", "//common:compiler_common", "//common:mutable_ast", @@ -55,12 +57,25 @@ java_library( "//common/navigation:mutable_navigation", "//common/types", "//common/types:type_providers", - "//extensions:optional_library", "//optimizer:ast_optimizer", "//optimizer:mutable_ast", - "//parser:operator", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven//:org_jspecify_jspecify", ], ) + +java_library( + name = "default_optimizer_constants", + srcs = [ + "DefaultOptimizerConstants.java", + ], + visibility = ["//visibility:private"], + deps = [ + "//checker:checker_legacy_environment", + "//extensions", + "//extensions:optional_library", + "//parser:operator", + "@maven//:com_google_guava_guava", + ], +) diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizer.java index 150f614df..7cf1ce1c3 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizer.java @@ -13,11 +13,14 @@ // limitations under the License. package dev.cel.optimizer.optimizers; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.MoreCollectors.onlyElement; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import dev.cel.bundle.Cel; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelMutableAst; @@ -40,6 +43,7 @@ import dev.cel.parser.Operator; import dev.cel.runtime.CelEvaluationException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -71,6 +75,7 @@ public static ConstantFoldingOptimizer newInstance( private final ConstantFoldingOptions constantFoldingOptions; private final AstMutator astMutator; + private final ImmutableSet foldableFunctions; // Use optional.of and optional.none as sentinel function names for folding optional calls. // TODO: Leverage CelValue representation of Optionals instead when available. @@ -95,7 +100,7 @@ public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) CelNavigableMutableAst.fromAst(mutableAst) .getRoot() .allNodes() - .filter(ConstantFoldingOptimizer::canFold) + .filter(this::canFold) .collect(toImmutableList()); for (CelNavigableMutableExpr foldableExpr : foldableExprs) { iterCount++; @@ -124,9 +129,13 @@ public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) return OptimizationResult.create(astMutator.renumberIdsConsecutively(mutableAst).toParsedAst()); } - private static boolean canFold(CelNavigableMutableExpr navigableExpr) { + private boolean canFold(CelNavigableMutableExpr navigableExpr) { switch (navigableExpr.getKind()) { case CALL: + if (!containsFoldableFunctionOnly(navigableExpr)) { + return false; + } + CelMutableCall mutableCall = navigableExpr.expr().call(); String functionName = mutableCall.function(); @@ -169,6 +178,19 @@ private static boolean canFold(CelNavigableMutableExpr navigableExpr) { } } + private boolean containsFoldableFunctionOnly(CelNavigableMutableExpr navigableExpr) { + return navigableExpr + .allNodes() + .allMatch( + node -> { + if (node.getKind().equals(Kind.CALL)) { + return foldableFunctions.contains(node.expr().call().function()); + } + + return true; + }); + } + private static boolean canFoldInOperator(CelNavigableMutableExpr navigableExpr) { ImmutableList allIdents = navigableExpr @@ -574,16 +596,39 @@ private CelMutableAst pruneOptionalStructElements(CelMutableAst ast, CelMutableE public abstract static class ConstantFoldingOptions { public abstract int maxIterationLimit(); + public abstract ImmutableSet foldableFunctions(); + /** Builder for configuring the {@link ConstantFoldingOptions}. */ @AutoValue.Builder public abstract static class Builder { + abstract ImmutableSet.Builder foldableFunctionsBuilder(); + /** * Limit the number of iteration while performing constant folding. An exception is thrown if * the iteration count exceeds the set value. */ public abstract Builder maxIterationLimit(int value); + /** + * Adds a collection of custom functions that will be a candidate for constant folding. By + * default, standard functions are foldable. + * + *

Note that the implementation of custom functions must be free of side effects. + */ + @CanIgnoreReturnValue + public Builder addFoldableFunctions(Iterable functions) { + checkNotNull(functions); + this.foldableFunctionsBuilder().addAll(functions); + return this; + } + + /** See {@link #addFoldableFunctions(Iterable)}. */ + @CanIgnoreReturnValue + public Builder addFoldableFunctions(String... functions) { + return addFoldableFunctions(Arrays.asList(functions)); + } + public abstract ConstantFoldingOptions build(); Builder() {} @@ -601,5 +646,10 @@ public static Builder newBuilder() { private ConstantFoldingOptimizer(ConstantFoldingOptions constantFoldingOptions) { this.constantFoldingOptions = constantFoldingOptions; this.astMutator = AstMutator.newInstance(constantFoldingOptions.maxIterationLimit()); + this.foldableFunctions = + ImmutableSet.builder() + .addAll(DefaultOptimizerConstants.CEL_CANONICAL_FUNCTIONS) + .addAll(constantFoldingOptions.foldableFunctions()) + .build(); } } diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/DefaultOptimizerConstants.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/DefaultOptimizerConstants.java new file mode 100644 index 000000000..07a3f062b --- /dev/null +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/DefaultOptimizerConstants.java @@ -0,0 +1,50 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.optimizer.optimizers; + +import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static java.util.Arrays.stream; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Streams; +import dev.cel.checker.Standard; +import dev.cel.extensions.CelExtensions; +import dev.cel.extensions.CelOptionalLibrary; +import dev.cel.extensions.CelOptionalLibrary.Function; +import dev.cel.parser.Operator; + +/** + * Package-private class that holds constants that's generally applicable across canonical + * optimizers provided from CEL. + */ +final class DefaultOptimizerConstants { + + /** + * List of function names from standard functions and extension libraries. These are free of side + * effects, thus amenable for optimization. + */ + static final ImmutableSet CEL_CANONICAL_FUNCTIONS = + ImmutableSet.builder() + .addAll( + Streams.concat( + stream(Operator.values()).map(Operator::getFunction), + stream(Standard.Function.values()).map(Standard.Function::getFunction), + stream(CelOptionalLibrary.Function.values()).map(Function::getFunction)) + .collect(toImmutableSet())) + .addAll(CelExtensions.getAllFunctionNames()) + .build(); + + private DefaultOptimizerConstants() {} +} diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java index 967c68d3c..ecb5b22e4 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java @@ -16,8 +16,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableList.toImmutableList; -import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static java.util.Arrays.stream; import static java.util.stream.Collectors.toCollection; import com.google.auto.value.AutoValue; @@ -30,7 +28,6 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import dev.cel.bundle.Cel; import dev.cel.bundle.CelBuilder; -import dev.cel.checker.Standard; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelMutableAst; @@ -54,12 +51,9 @@ import dev.cel.common.types.CelType; import dev.cel.common.types.ListType; import dev.cel.common.types.SimpleType; -import dev.cel.extensions.CelOptionalLibrary; -import dev.cel.extensions.CelOptionalLibrary.Function; import dev.cel.optimizer.AstMutator; import dev.cel.optimizer.AstMutator.MangledComprehensionAst; import dev.cel.optimizer.CelAstOptimizer; -import dev.cel.parser.Operator; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -94,12 +88,7 @@ * */ public class SubexpressionOptimizer implements CelAstOptimizer { - private static final ImmutableSet CSE_DEFAULT_ELIMINABLE_FUNCTIONS = - Streams.concat( - stream(Operator.values()).map(Operator::getFunction), - stream(Standard.Function.values()).map(Standard.Function::getFunction), - stream(CelOptionalLibrary.Function.values()).map(Function::getFunction)) - .collect(toImmutableSet()); + private static final SubexpressionOptimizer INSTANCE = new SubexpressionOptimizer(SubexpressionOptimizerOptions.newBuilder().build()); private static final String BIND_IDENTIFIER_PREFIX = "@r"; @@ -738,7 +727,7 @@ private SubexpressionOptimizer(SubexpressionOptimizerOptions cseOptions) { this.astMutator = AstMutator.newInstance(cseOptions.iterationLimit()); this.cseEliminableFunctions = ImmutableSet.builder() - .addAll(CSE_DEFAULT_ELIMINABLE_FUNCTIONS) + .addAll(DefaultOptimizerConstants.CEL_CANONICAL_FUNCTIONS) .addAll(cseOptions.eliminableFunctions()) .build(); } diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java index 9813ee266..96040b508 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java @@ -17,12 +17,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.common.collect.ImmutableList; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.bundle.Cel; import dev.cel.bundle.CelFactory; import dev.cel.common.CelAbstractSyntaxTree; +import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; +import dev.cel.common.CelOverloadDecl; import dev.cel.common.types.ListType; import dev.cel.common.types.MapType; import dev.cel.common.types.SimpleType; @@ -35,6 +38,7 @@ import dev.cel.parser.CelStandardMacro; import dev.cel.parser.CelUnparser; import dev.cel.parser.CelUnparserFactory; +import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -47,10 +51,27 @@ public class ConstantFoldingOptimizerTest { .addVar("y", SimpleType.DYN) .addVar("list_var", ListType.create(SimpleType.STRING)) .addVar("map_var", MapType.create(SimpleType.STRING, SimpleType.STRING)) + .addFunctionDeclarations( + CelFunctionDecl.newFunctionDeclaration( + "get_true", + CelOverloadDecl.newGlobalOverload("get_true_overload", SimpleType.BOOL))) + .addFunctionBindings( + CelFunctionBinding.from("get_true_overload", ImmutableList.of(), unused -> true)) .addMessageTypes(TestAllTypes.getDescriptor()) .setContainer("dev.cel.testing.testdata.proto3") - .addCompilerLibraries(CelExtensions.bindings(), CelOptionalLibrary.INSTANCE) - .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) + .addCompilerLibraries( + CelExtensions.bindings(), + CelOptionalLibrary.INSTANCE, + CelExtensions.math(CelOptions.DEFAULT), + CelExtensions.strings(), + CelExtensions.sets(), + CelExtensions.encoders()) + .addRuntimeLibraries( + CelOptionalLibrary.INSTANCE, + CelExtensions.math(CelOptions.DEFAULT), + CelExtensions.strings(), + CelExtensions.sets(), + CelExtensions.encoders()) .build(); private static final CelOptimizer CEL_OPTIMIZER = @@ -161,6 +182,10 @@ public class ConstantFoldingOptimizerTest { @TestParameters("{source: 'map_var[?\"key\"]', expected: 'map_var[?\"key\"]'}") @TestParameters("{source: '\"abc\" in list_var', expected: '\"abc\" in list_var'}") @TestParameters("{source: '[?optional.none(), [?optional.none()]]', expected: '[[]]'}") + @TestParameters("{source: 'math.greatest(1.0, 2, 3.0)', expected: '3.0'}") + @TestParameters("{source: '\"world\".charAt(1)', expected: '\"o\"'}") + @TestParameters("{source: 'base64.encode(b\"hello\")', expected: '\"aGVsbG8=\"'}") + @TestParameters("{source: 'sets.contains([1], [1])', expected: 'true'}") @TestParameters( "{source: 'cel.bind(r0, [1, 2, 3], cel.bind(r1, 1 in r0, r1))', expected: 'true'}") // TODO: Support folding lists with mixed types. This requires mutable lists. @@ -291,6 +316,8 @@ public void constantFold_macros_withoutMacroCallMetadata(String source) throws E @TestParameters("{source: '[optional.none()]'}") @TestParameters("{source: '[?x.?y]'}") @TestParameters("{source: 'TestAllTypes{single_int32: x, repeated_int32: [1, 2, 3]}'}") + @TestParameters("{source: 'get_true() == get_true()'}") + @TestParameters("{source: 'get_true() == true'}") public void constantFold_noOp(String source) throws Exception { CelAbstractSyntaxTree ast = CEL.compile(source).getAst(); @@ -299,6 +326,21 @@ public void constantFold_noOp(String source) throws Exception { assertThat(CEL_UNPARSER.unparse(optimizedAst)).isEqualTo(source); } + @Test + public void constantFold_addFoldableFunction_success() throws Exception { + CelAbstractSyntaxTree ast = CEL.compile("get_true() == get_true()").getAst(); + ConstantFoldingOptions options = + ConstantFoldingOptions.newBuilder().addFoldableFunctions("get_true").build(); + CelOptimizer optimizer = + CelOptimizerFactory.standardCelOptimizerBuilder(CEL) + .addAstOptimizers(ConstantFoldingOptimizer.newInstance(options)) + .build(); + + CelAbstractSyntaxTree optimizedAst = optimizer.optimize(ast); + + assertThat(CEL_UNPARSER.unparse(optimizedAst)).isEqualTo("true"); + } + @Test public void constantFold_withMacroCallPopulated_comprehensionsAreReplacedWithNotSet() throws Exception { From 77d78530081736db644422aa4e7693c61e1346cb Mon Sep 17 00:00:00 2001 From: Tristan Swadell Date: Wed, 24 Jul 2024 15:03:19 -0700 Subject: [PATCH 03/33] Introduce ProtoUnsetFieldOptions to support unset handling like C++ PiperOrigin-RevId: 655712342 --- .../main/java/dev/cel/common/CelOptions.java | 26 ++++++++++++++- .../main/java/dev/cel/runtime/Activation.java | 8 +++++ .../java/dev/cel/runtime/ActivationTest.java | 33 +++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/dev/cel/common/CelOptions.java b/common/src/main/java/dev/cel/common/CelOptions.java index fb5ec6ad7..c5288aa2f 100644 --- a/common/src/main/java/dev/cel/common/CelOptions.java +++ b/common/src/main/java/dev/cel/common/CelOptions.java @@ -30,6 +30,18 @@ @Immutable public abstract class CelOptions { + /** + * ProtoUnsetFieldOptions describes how to handle Activation.fromProto() calls where proto message + * fields may be unset and should either be handled perhaps as absent or as the default proto + * value. + */ + public enum ProtoUnsetFieldOptions { + // Do not bind a field if it is unset. Repeated fields are bound as empty list. + SKIP, + // Bind the (proto api) default value for a field. + BIND_DEFAULT; + } + public static final CelOptions DEFAULT = current().build(); public static final CelOptions LEGACY = newBuilder().disableCelStandardEquality(true).build(); @@ -95,6 +107,8 @@ public abstract class CelOptions { public abstract boolean unwrapWellKnownTypesOnFunctionDispatch(); + public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption(); + public abstract Builder toBuilder(); public ImmutableSet toExprFeatures() { @@ -185,7 +199,8 @@ public static Builder newBuilder() { .enableUnknownTracking(false) .enableCelValue(false) .comprehensionMaxIterations(-1) - .unwrapWellKnownTypesOnFunctionDispatch(true); + .unwrapWellKnownTypesOnFunctionDispatch(true) + .fromProtoUnsetFieldOption(ProtoUnsetFieldOptions.BIND_DEFAULT); } /** @@ -479,6 +494,15 @@ public abstract static class Builder { @Deprecated public abstract Builder unwrapWellKnownTypesOnFunctionDispatch(boolean value); + /** + * Configure how unset proto fields are handled when evaluating over a protobuf message where + * fields are intended to be treated as top-level variables. Defaults to binding all fields to + * their default value if unset. + * + * @see ProtoUnsetFieldOptions + */ + public abstract Builder fromProtoUnsetFieldOption(ProtoUnsetFieldOptions value); + public abstract CelOptions build(); } } diff --git a/runtime/src/main/java/dev/cel/runtime/Activation.java b/runtime/src/main/java/dev/cel/runtime/Activation.java index 1894c16ca..0ea70662e 100644 --- a/runtime/src/main/java/dev/cel/runtime/Activation.java +++ b/runtime/src/main/java/dev/cel/runtime/Activation.java @@ -172,7 +172,15 @@ public static Activation fromProto(Message message, CelOptions celOptions) { new ProtoAdapter( DynamicProto.create(DefaultMessageFactory.INSTANCE), celOptions.enableUnsignedLongs()); + boolean skipUnsetFields = + celOptions.fromProtoUnsetFieldOption().equals(CelOptions.ProtoUnsetFieldOptions.SKIP); + for (FieldDescriptor field : message.getDescriptorForType().getFields()) { + // If skipping unset fields and the field is not repeated, then continue. + if (skipUnsetFields && !field.isRepeated() && !msgFieldValues.containsKey(field)) { + continue; + } + // Get the value of the field set on the message, if present, otherwise use reflection to // get the default value for the field using the FieldDescriptor. Object fieldValue = msgFieldValues.getOrDefault(field, message.getField(field)); diff --git a/runtime/src/test/java/dev/cel/runtime/ActivationTest.java b/runtime/src/test/java/dev/cel/runtime/ActivationTest.java index 5eb10737c..04bc1cfb2 100644 --- a/runtime/src/test/java/dev/cel/runtime/ActivationTest.java +++ b/runtime/src/test/java/dev/cel/runtime/ActivationTest.java @@ -35,6 +35,13 @@ public final class ActivationTest { private static final CelOptions TEST_OPTIONS = CelOptions.current().enableTimestampEpoch(true).enableUnsignedLongs(true).build(); + private static final CelOptions TEST_OPTIONS_SKIP_UNSET_FIELDS = + CelOptions.current() + .enableTimestampEpoch(true) + .enableUnsignedLongs(true) + .fromProtoUnsetFieldOption(CelOptions.ProtoUnsetFieldOptions.SKIP) + .build(); + @Test public void copyOf_success_withNullEntries() { Map map = new HashMap<>(); @@ -64,6 +71,13 @@ public void fromProto_unsetScalarField() { assertThat(activation.resolve("bb")).isEqualTo(0); } + @Test + public void fromProto_unsetScalarField_skipUnsetFields() { + Activation activation = + Activation.fromProto(NestedMessage.getDefaultInstance(), TEST_OPTIONS_SKIP_UNSET_FIELDS); + assertThat(activation.resolve("bb")).isNull(); + } + @Test public void fromProto_unsetAnyField() { // An unset Any field is the only field which cannot be accurately published into an Activation, @@ -102,6 +116,17 @@ public void fromProto_unsetRepeatedField() { assertThat((List) activation.resolve("repeated_nested_message")).isEmpty(); } + @Test + public void fromProto_unsetRepeatedField_skipUnsetFields() { + Activation activation = + Activation.fromProto(TestAllTypes.getDefaultInstance(), TEST_OPTIONS_SKIP_UNSET_FIELDS); + assertThat(activation.resolve("repeated_int64")).isInstanceOf(List.class); + assertThat((List) activation.resolve("repeated_int64")).isEmpty(); + + assertThat(activation.resolve("repeated_nested_message")).isInstanceOf(List.class); + assertThat((List) activation.resolve("repeated_nested_message")).isEmpty(); + } + @Test public void fromProto_unsetMapField() { Activation activation = Activation.fromProto(TestAllTypes.getDefaultInstance(), TEST_OPTIONS); @@ -109,6 +134,14 @@ public void fromProto_unsetMapField() { assertThat((Map) activation.resolve("map_int32_int64")).isEmpty(); } + @Test + public void fromProto_unsetMapField_skipUnsetFields() { + Activation activation = + Activation.fromProto(TestAllTypes.getDefaultInstance(), TEST_OPTIONS_SKIP_UNSET_FIELDS); + assertThat(activation.resolve("map_int32_int64")).isInstanceOf(Map.class); + assertThat((Map) activation.resolve("map_int32_int64")).isEmpty(); + } + @Test public void fromProto_unsignedLongField_unsignedResult() { Activation activation = From f78c6c4944f545e6984d2c0a20c272a41f1494e1 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Tue, 30 Jul 2024 13:39:04 -0700 Subject: [PATCH 04/33] Fix conditionally nested rules to include its condition PiperOrigin-RevId: 657714654 --- .../java/dev/cel/policy/CelCompiledRule.java | 4 +- .../cel/policy/CelPolicyYamlConfigParser.java | 14 +++++- .../java/dev/cel/policy/RuleComposer.java | 21 ++++++-- .../main/java/dev/cel/policy/YamlHelper.java | 13 ++++- .../policy/CelPolicyYamlConfigParserTest.java | 36 +++++++++++++ .../java/dev/cel/policy/PolicyTestHelper.java | 13 ++++- policy/src/test/resources/limits/config.yaml | 22 ++++++++ policy/src/test/resources/limits/policy.yaml | 50 +++++++++++++++++++ policy/src/test/resources/limits/tests.yaml | 38 ++++++++++++++ 9 files changed, 202 insertions(+), 9 deletions(-) create mode 100644 policy/src/test/resources/limits/config.yaml create mode 100644 policy/src/test/resources/limits/policy.yaml create mode 100644 policy/src/test/resources/limits/tests.yaml diff --git a/policy/src/main/java/dev/cel/policy/CelCompiledRule.java b/policy/src/main/java/dev/cel/policy/CelCompiledRule.java index 4c39fee94..3c5893dfb 100644 --- a/policy/src/main/java/dev/cel/policy/CelCompiledRule.java +++ b/policy/src/main/java/dev/cel/policy/CelCompiledRule.java @@ -94,7 +94,9 @@ public enum Kind { */ @AutoValue public abstract static class OutputValue { - public abstract long id(); + + /** Source metadata identifier associated with the output. */ + public abstract long sourceId(); public abstract CelAbstractSyntaxTree ast(); diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyYamlConfigParser.java b/policy/src/main/java/dev/cel/policy/CelPolicyYamlConfigParser.java index f0525f7ef..6d84c8fcb 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyYamlConfigParser.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyYamlConfigParser.java @@ -21,6 +21,7 @@ import static dev.cel.policy.YamlHelper.newInteger; import static dev.cel.policy.YamlHelper.newString; import static dev.cel.policy.YamlHelper.parseYamlSource; +import static dev.cel.policy.YamlHelper.validateYamlType; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -258,7 +259,18 @@ private static ExtensionConfig parseExtension(ParserContext ctx, Node node builder.setName(newString(ctx, valueNode)); break; case "version": - builder.setVersion(newInteger(ctx, valueNode)); + if (validateYamlType(valueNode, YamlNodeType.INTEGER)) { + builder.setVersion(newInteger(ctx, valueNode)); + break; + } else if (validateYamlType(valueNode, YamlNodeType.STRING, YamlNodeType.TEXT)) { + String versionStr = newString(ctx, valueNode); + if (versionStr.equals("latest")) { + builder.setVersion(Integer.MAX_VALUE); + break; + } + // Fall-through + } + ctx.reportError(keyId, String.format("Unsupported version tag: %s", keyName)); break; default: ctx.reportError(keyId, String.format("Unsupported extension tag: %s", keyName)); diff --git a/policy/src/main/java/dev/cel/policy/RuleComposer.java b/policy/src/main/java/dev/cel/policy/RuleComposer.java index 732b60394..c3b888887 100644 --- a/policy/src/main/java/dev/cel/policy/RuleComposer.java +++ b/policy/src/main/java/dev/cel/policy/RuleComposer.java @@ -85,7 +85,7 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul if (isTriviallyTrue) { matchAst = outAst; isOptionalResult = false; - lastOutputId = matchOutput.id(); + lastOutputId = matchOutput.sourceId(); continue; } if (isOptionalResult) { @@ -99,8 +99,12 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul outAst, matchAst); assertComposedAstIsValid( - cel, matchAst, "conflicting output types found.", matchOutput.id(), lastOutputId); - lastOutputId = matchOutput.id(); + cel, + matchAst, + "conflicting output types found.", + matchOutput.sourceId(), + lastOutputId); + lastOutputId = matchOutput.sourceId(); continue; case RULE: CelCompiledRule matchNestedRule = match.result().rule(); @@ -117,7 +121,16 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul if (!isOptionalResult && !nestedRule.isOptionalResult()) { throw new IllegalArgumentException("Subrule early terminates policy"); } - matchAst = astMutator.newMemberCall(nestedRuleAst, Function.OR.getFunction(), matchAst); + if (isTriviallyTrue) { + matchAst = astMutator.newMemberCall(nestedRuleAst, Function.OR.getFunction(), matchAst); + } else { + matchAst = + astMutator.newGlobalCall( + Operator.CONDITIONAL.getFunction(), + CelMutableAst.fromCelAst(conditionAst), + nestedRuleAst, + matchAst); + } assertComposedAstIsValid( cel, matchAst, diff --git a/policy/src/main/java/dev/cel/policy/YamlHelper.java b/policy/src/main/java/dev/cel/policy/YamlHelper.java index d340ce329..276c09be4 100644 --- a/policy/src/main/java/dev/cel/policy/YamlHelper.java +++ b/policy/src/main/java/dev/cel/policy/YamlHelper.java @@ -69,14 +69,23 @@ static boolean assertRequiredFields( return false; } - static boolean assertYamlType( - ParserContext ctx, long id, Node node, YamlNodeType... expectedNodeTypes) { + static boolean validateYamlType(Node node, YamlNodeType... expectedNodeTypes) { String nodeTag = node.getTag().getValue(); for (YamlNodeType expectedNodeType : expectedNodeTypes) { if (expectedNodeType.tag().equals(nodeTag)) { return true; } } + return false; + } + + static boolean assertYamlType( + ParserContext ctx, long id, Node node, YamlNodeType... expectedNodeTypes) { + if (validateYamlType(node, expectedNodeTypes)) { + return true; + } + String nodeTag = node.getTag().getValue(); + ctx.reportError( id, String.format( diff --git a/policy/src/test/java/dev/cel/policy/CelPolicyYamlConfigParserTest.java b/policy/src/test/java/dev/cel/policy/CelPolicyYamlConfigParserTest.java index 6da658729..630bfc76e 100644 --- a/policy/src/test/java/dev/cel/policy/CelPolicyYamlConfigParserTest.java +++ b/policy/src/test/java/dev/cel/policy/CelPolicyYamlConfigParserTest.java @@ -91,6 +91,42 @@ public void config_setExtensions() throws Exception { assertThat(policyConfig.extend(CEL_WITH_MESSAGE_TYPES, CelOptions.DEFAULT)).isNotNull(); } + @Test + public void config_setExtensionVersionToLatest() throws Exception { + String yamlConfig = + "extensions:\n" // + + " - name: 'bindings'\n" // + + " version: latest"; + + CelPolicyConfig policyConfig = POLICY_CONFIG_PARSER.parse(yamlConfig); + + assertThat(policyConfig) + .isEqualTo( + CelPolicyConfig.newBuilder() + .setConfigSource(policyConfig.configSource()) + .setExtensions(ImmutableSet.of(ExtensionConfig.of("bindings", Integer.MAX_VALUE))) + .build()); + assertThat(policyConfig.extend(CEL_WITH_MESSAGE_TYPES, CelOptions.DEFAULT)).isNotNull(); + } + + @Test + public void config_setExtensionVersionToInvalidValue() throws Exception { + String yamlConfig = + "extensions:\n" // + + " - name: 'bindings'\n" // + + " version: invalid"; + + CelPolicyValidationException e = + assertThrows( + CelPolicyValidationException.class, () -> POLICY_CONFIG_PARSER.parse(yamlConfig)); + assertThat(e) + .hasMessageThat() + .contains( + "ERROR: :3:5: Unsupported version tag: version\n" + + " | version: invalid\n" + + " | ....^"); + } + @Test public void config_setFunctions() throws Exception { String yamlConfig = diff --git a/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java index f323e5ca5..a41f398d1 100644 --- a/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java +++ b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java @@ -87,7 +87,18 @@ enum TestYamlPolicy { "pb", true, "(spec.single_int32 > 10) ? optional.of(\"invalid spec, got single_int32=\" +" - + " string(spec.single_int32) + \", wanted <= 10\") : optional.none()"); + + " string(spec.single_int32) + \", wanted <= 10\") : optional.none()"), + LIMITS( + "limits", + true, + "cel.bind(variables.greeting, \"hello\", cel.bind(variables.farewell, \"goodbye\"," + + " cel.bind(variables.person, \"me\", cel.bind(variables.message_fmt, \"%s, %s\"," + + " (now.getHours() >= 20) ? cel.bind(variables.message, variables.farewell + \", \" +" + + " variables.person, (now.getHours() < 21) ? optional.of(variables.message + \"!\") :" + + " ((now.getHours() < 22) ? optional.of(variables.message + \"!!\") : ((now.getHours()" + + " < 24) ? optional.of(variables.message + \"!!!\") : optional.none()))) :" + + " optional.of(variables.greeting + \", \" + variables.person)))))"); + private final String name; private final boolean producesOptionalResult; private final String unparsed; diff --git a/policy/src/test/resources/limits/config.yaml b/policy/src/test/resources/limits/config.yaml new file mode 100644 index 000000000..fa6fc737c --- /dev/null +++ b/policy/src/test/resources/limits/config.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: "limits" +extensions: +- name: "strings" + version: latest +variables: +- name: "now" + type: + type_name: "google.protobuf.Timestamp" \ No newline at end of file diff --git a/policy/src/test/resources/limits/policy.yaml b/policy/src/test/resources/limits/policy.yaml new file mode 100644 index 000000000..13c47c39b --- /dev/null +++ b/policy/src/test/resources/limits/policy.yaml @@ -0,0 +1,50 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: "limits" +rule: + variables: + - name: "greeting" + expression: "'hello'" + - name: "farewell" + expression: "'goodbye'" + - name: "person" + expression: "'me'" + - name: "message_fmt" + expression: "'%s, %s'" + match: + - condition: | + now.getHours() >= 20 + rule: + id: "farewells" + variables: + - name: "message" + expression: > + variables.farewell + ', ' + variables.person +# TODO: replace when string.format is available +# variables.message_fmt.format([variables.farewell, +# variables.person]) + match: + - condition: > + now.getHours() < 21 + output: variables.message + "!" + - condition: > + now.getHours() < 22 + output: variables.message + "!!" + - condition: > + now.getHours() < 24 + output: variables.message + "!!!" + - output: > + variables.greeting + ', ' + variables.person +# variables.message_fmt.format([variables.greeting, variables.person]) TODO: replace when string.format is available \ No newline at end of file diff --git a/policy/src/test/resources/limits/tests.yaml b/policy/src/test/resources/limits/tests.yaml new file mode 100644 index 000000000..fe6daa61d --- /dev/null +++ b/policy/src/test/resources/limits/tests.yaml @@ -0,0 +1,38 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +description: Limits related tests +section: +- name: "now_after_hours" + tests: + - name: "7pm" + input: + now: + expr: "timestamp('2024-07-30T00:30:00Z')" + output: "'hello, me'" + - name: "8pm" + input: + now: + expr: "timestamp('2024-07-30T20:30:00Z')" + output: "'goodbye, me!'" + - name: "9pm" + input: + now: + expr: "timestamp('2024-07-30T21:30:00Z')" + output: "'goodbye, me!!'" + - name: "11pm" + input: + now: + expr: "timestamp('2024-07-30T23:30:00Z')" + output: "'goodbye, me!!!'" \ No newline at end of file From 5b85b76c12e5a400ace4a772a667dc8c6a8fde60 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 1 Aug 2024 13:02:46 -0700 Subject: [PATCH 05/33] Remove unused list/map conversion functions from standard definitions PiperOrigin-RevId: 658509637 --- .../main/java/dev/cel/checker/Standard.java | 19 ------------------- .../test/resources/standardEnvDump.baseline | 2 -- 2 files changed, 21 deletions(-) diff --git a/checker/src/main/java/dev/cel/checker/Standard.java b/checker/src/main/java/dev/cel/checker/Standard.java index f595dde9a..1781fe559 100644 --- a/checker/src/main/java/dev/cel/checker/Standard.java +++ b/checker/src/main/java/dev/cel/checker/Standard.java @@ -419,25 +419,6 @@ private static ImmutableList coreFunctionDeclarations() { CelOverloadDecl.newGlobalOverload( "duration_to_string", "type_conversion", SimpleType.STRING, SimpleType.DURATION))); - // Conversions to list - celFunctionDeclBuilder.add( - CelFunctionDecl.newFunctionDeclaration( - Function.LIST.getFunction(), - CelOverloadDecl.newGlobalOverload( - "to_list", "type conversion", listOfA, TypeType.create(typeParamA), listOfA))); - - // Conversions to map - celFunctionDeclBuilder.add( - CelFunctionDecl.newFunctionDeclaration( - Function.MAP.getFunction(), - CelOverloadDecl.newGlobalOverload( - "to_map", - "type conversion", - mapOfAb, - TypeType.create(typeParamA), - TypeType.create(typeParamB), - mapOfAb))); - // Conversions to bytes celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( diff --git a/checker/src/test/resources/standardEnvDump.baseline b/checker/src/test/resources/standardEnvDump.baseline index 4ef2fa9cf..a49852d84 100644 --- a/checker/src/test/resources/standardEnvDump.baseline +++ b/checker/src/test/resources/standardEnvDump.baseline @@ -220,11 +220,9 @@ declare int { } declare list { value type(list(dyn)) - function to_list (type(A), list(A)) -> list(A) } declare map { value type(map(dyn, dyn)) - function to_map (type(A), type(B), map(A, B)) -> map(A, B) } declare matches { function matches (string, string) -> bool From ea16dc41c5c4e851abc7bf3cef10d14466c5f98b Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 1 Aug 2024 14:57:15 -0700 Subject: [PATCH 06/33] Include identity functions in the standard definitions PiperOrigin-RevId: 658548681 --- .../src/main/java/dev/cel/checker/Env.java | 4 ++ .../main/java/dev/cel/checker/Standard.java | 41 ++++++++++++++++++- .../test/resources/standardEnvDump.baseline | 8 ++++ .../dev/cel/runtime/StandardFunctions.java | 22 ++++++++++ .../test/resources/boolConversions.baseline | 4 ++ .../test/resources/bytesConversions.baseline | 5 +++ .../test/resources/doubleConversions.baseline | 5 +++ .../test/resources/stringConversions.baseline | 5 +++ .../test/resources/timeConversions.baseline | 17 ++++++++ .../test/resources/uint64Conversions.baseline | 10 +++++ .../dev/cel/testing/BaseInterpreterTest.java | 27 ++++++++++++ 11 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 runtime/src/test/resources/boolConversions.baseline diff --git a/checker/src/main/java/dev/cel/checker/Env.java b/checker/src/main/java/dev/cel/checker/Env.java index 8cc354fb2..613bef166 100644 --- a/checker/src/main/java/dev/cel/checker/Env.java +++ b/checker/src/main/java/dev/cel/checker/Env.java @@ -540,6 +540,10 @@ boolean enableTimestampEpoch() { return celOptions.enableTimestampEpoch(); } + boolean enableUnsignedLongs() { + return celOptions.enableUnsignedLongs(); + } + /** Add an identifier {@code decl} to the environment. */ @CanIgnoreReturnValue private Env addIdent(CelIdentDecl celIdentDecl) { diff --git a/checker/src/main/java/dev/cel/checker/Standard.java b/checker/src/main/java/dev/cel/checker/Standard.java index 1781fe559..eaac8c300 100644 --- a/checker/src/main/java/dev/cel/checker/Standard.java +++ b/checker/src/main/java/dev/cel/checker/Standard.java @@ -99,6 +99,14 @@ public static Env add(Env env) { timestampConversionDeclarations(env.enableTimestampEpoch()).forEach(env::add); numericComparisonDeclarations(env.enableHeterogeneousNumericComparisons()).forEach(env::add); + if (env.enableUnsignedLongs()) { + env.add( + CelFunctionDecl.newFunctionDeclaration( + Function.INT.getFunction(), + CelOverloadDecl.newGlobalOverload( + "int64_to_int64", "type conversion (identity)", SimpleType.INT, SimpleType.INT))); + } + return env; } @@ -384,6 +392,8 @@ private static ImmutableList coreFunctionDeclarations() { celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( Function.UINT.getFunction(), + CelOverloadDecl.newGlobalOverload( + "uint64_to_uint64", "type conversion (identity)", SimpleType.UINT, SimpleType.UINT), CelOverloadDecl.newGlobalOverload( "int64_to_uint64", "type conversion", SimpleType.UINT, SimpleType.INT), CelOverloadDecl.newGlobalOverload( @@ -395,6 +405,11 @@ private static ImmutableList coreFunctionDeclarations() { celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( Function.DOUBLE.getFunction(), + CelOverloadDecl.newGlobalOverload( + "double_to_double", + "type conversion (identity)", + SimpleType.DOUBLE, + SimpleType.DOUBLE), CelOverloadDecl.newGlobalOverload( "int64_to_double", "type conversion", SimpleType.DOUBLE, SimpleType.INT), CelOverloadDecl.newGlobalOverload( @@ -406,6 +421,11 @@ private static ImmutableList coreFunctionDeclarations() { celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( Function.STRING.getFunction(), + CelOverloadDecl.newGlobalOverload( + "string_to_string", + "type conversion (identity)", + SimpleType.STRING, + SimpleType.STRING), CelOverloadDecl.newGlobalOverload( "int64_to_string", "type conversion", SimpleType.STRING, SimpleType.INT), CelOverloadDecl.newGlobalOverload( @@ -423,6 +443,8 @@ private static ImmutableList coreFunctionDeclarations() { celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( Function.BYTES.getFunction(), + CelOverloadDecl.newGlobalOverload( + "bytes_to_bytes", "type conversion (identity)", SimpleType.BYTES, SimpleType.BYTES), CelOverloadDecl.newGlobalOverload( "string_to_bytes", "type conversion", SimpleType.BYTES, SimpleType.STRING))); @@ -437,12 +459,24 @@ private static ImmutableList coreFunctionDeclarations() { celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( Function.DURATION.getFunction(), + CelOverloadDecl.newGlobalOverload( + "duration_to_duration", + "type conversion (identity)", + SimpleType.DURATION, + SimpleType.DURATION), CelOverloadDecl.newGlobalOverload( "string_to_duration", "type conversion, duration should be end with \"s\", which stands for seconds", SimpleType.DURATION, SimpleType.STRING))); + // Conversions to boolean + celFunctionDeclBuilder.add( + CelFunctionDecl.newFunctionDeclaration( + Function.BOOL.getFunction(), + CelOverloadDecl.newGlobalOverload( + "bool_to_bool", "type conversion (identity)", SimpleType.BOOL, SimpleType.BOOL))); + // String functions celFunctionDeclBuilder.add( CelFunctionDecl.newFunctionDeclaration( @@ -674,7 +708,12 @@ private static ImmutableList timestampConversionDeclarations(bo "Type conversion of strings to timestamps according to RFC3339. Example:" + " \"1972-01-01T10:00:20.021-05:00\".", SimpleType.TIMESTAMP, - SimpleType.STRING)); + SimpleType.STRING), + CelOverloadDecl.newGlobalOverload( + "timestamp_to_timestamp", + "type conversion (identity)", + SimpleType.TIMESTAMP, + SimpleType.TIMESTAMP)); if (withEpoch) { timestampBuilder.addOverloads( CelOverloadDecl.newGlobalOverload( diff --git a/checker/src/test/resources/standardEnvDump.baseline b/checker/src/test/resources/standardEnvDump.baseline index a49852d84..5f88f7f50 100644 --- a/checker/src/test/resources/standardEnvDump.baseline +++ b/checker/src/test/resources/standardEnvDump.baseline @@ -143,9 +143,11 @@ declare _||_ { } declare bool { value type(bool) + function bool_to_bool (bool) -> bool } declare bytes { value type(bytes) + function bytes_to_bytes (bytes) -> bytes function string_to_bytes (string) -> bytes } declare contains { @@ -153,11 +155,13 @@ declare contains { } declare double { value type(double) + function double_to_double (double) -> double function int64_to_double (int) -> double function uint64_to_double (uint) -> double function string_to_double (string) -> double } declare duration { + function duration_to_duration (google.protobuf.Duration) -> google.protobuf.Duration function string_to_duration (string) -> google.protobuf.Duration } declare dyn { @@ -217,6 +221,7 @@ declare int { function double_to_int64 (double) -> int function string_to_int64 (string) -> int function timestamp_to_int64 (google.protobuf.Timestamp) -> int + function int64_to_int64 (int) -> int } declare list { value type(list(dyn)) @@ -246,6 +251,7 @@ declare startsWith { } declare string { value type(string) + function string_to_string (string) -> string function int64_to_string (int) -> string function uint64_to_string (uint) -> string function double_to_string (double) -> string @@ -255,6 +261,7 @@ declare string { } declare timestamp { function string_to_timestamp (string) -> google.protobuf.Timestamp + function timestamp_to_timestamp (google.protobuf.Timestamp) -> google.protobuf.Timestamp function int64_to_timestamp (int) -> google.protobuf.Timestamp } declare type { @@ -263,6 +270,7 @@ declare type { } declare uint { value type(uint) + function uint64_to_uint64 (uint) -> uint function int64_to_uint64 (int) -> uint function double_to_uint64 (double) -> uint function string_to_uint64 (string) -> uint diff --git a/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java b/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java index d7d00fdaa..23a77c0c7 100644 --- a/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java +++ b/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java @@ -154,6 +154,8 @@ public static void addNonInlined( } private static void addBoolFunctions(Registrar registrar) { + // Identity + registrar.add("bool_to_bool", Boolean.class, (Boolean x) -> x); // The conditional, logical_or, logical_and, and not_strictly_false functions are special-cased. registrar.add("logical_not", Boolean.class, (Boolean x) -> !x); @@ -167,6 +169,8 @@ private static void addBoolFunctions(Registrar registrar) { } private static void addBytesFunctions(Registrar registrar) { + // Identity + registrar.add("bytes_to_bytes", ByteString.class, (ByteString x) -> x); // Bytes ordering functions: <, <=, >=, > registrar.add( "less_bytes", @@ -205,6 +209,8 @@ private static void addBytesFunctions(Registrar registrar) { } private static void addDoubleFunctions(Registrar registrar, CelOptions celOptions) { + // Identity + registrar.add("double_to_double", Double.class, (Double x) -> x); // Double ordering functions. registrar.add("less_double", Double.class, Double.class, (Double x, Double y) -> x < y); registrar.add("less_equals_double", Double.class, Double.class, (Double x, Double y) -> x <= y); @@ -245,6 +251,8 @@ private static void addDoubleFunctions(Registrar registrar, CelOptions celOption } private static void addDurationFunctions(Registrar registrar) { + // Identity + registrar.add("duration_to_duration", Duration.class, (Duration x) -> x); // Duration ordering functions: <, <=, >=, > registrar.add( "less_duration", @@ -307,6 +315,12 @@ private static void addDurationFunctions(Registrar registrar) { } private static void addIntFunctions(Registrar registrar, CelOptions celOptions) { + // Identity + if (celOptions.enableUnsignedLongs()) { + // Note that we require UnsignedLong flag here to avoid ambiguous overloads against + // "uint64_to_int64", because they both use the same Java Long class. + registrar.add("int64_to_int64", Long.class, (Long x) -> x); + } // Comparison functions. registrar.add("less_int64", Long.class, Long.class, (Long x, Long y) -> x < y); registrar.add("less_equals_int64", Long.class, Long.class, (Long x, Long y) -> x <= y); @@ -499,6 +513,8 @@ private static void addMapFunctions( } private static void addStringFunctions(Registrar registrar, CelOptions celOptions) { + // Identity + registrar.add("string_to_string", String.class, (String x) -> x); // String ordering functions: <, <=, >=, >. registrar.add( "less_string", String.class, String.class, (String x, String y) -> x.compareTo(y) < 0); @@ -547,6 +563,8 @@ private static void addStringFunctions(Registrar registrar, CelOptions celOption // timestamp_to_milliseconds overload @SuppressWarnings("JavaLocalDateTimeGetNano") private static void addTimestampFunctions(Registrar registrar) { + // Identity + registrar.add("timestamp_to_timestamp", Timestamp.class, (Timestamp x) -> x); // Timestamp relation operators: <, <=, >=, > registrar.add( "less_timestamp", @@ -714,6 +732,8 @@ private static void addTimestampFunctions(Registrar registrar) { } private static void addSignedUintFunctions(Registrar registrar, CelOptions celOptions) { + // Identity + registrar.add("uint64_to_uint64", Long.class, (Long x) -> x); // Uint relation operators: <, <=, >=, > registrar.add( "less_uint64", @@ -833,6 +853,8 @@ private static void addSignedUintFunctions(Registrar registrar, CelOptions celOp } private static void addUintFunctions(Registrar registrar, CelOptions celOptions) { + // Identity + registrar.add("uint64_to_uint64", UnsignedLong.class, (UnsignedLong x) -> x); registrar.add( "less_uint64", UnsignedLong.class, diff --git a/runtime/src/test/resources/boolConversions.baseline b/runtime/src/test/resources/boolConversions.baseline new file mode 100644 index 000000000..3d7415aba --- /dev/null +++ b/runtime/src/test/resources/boolConversions.baseline @@ -0,0 +1,4 @@ +Source: bool(true) +=====> +bindings: {} +result: true \ No newline at end of file diff --git a/runtime/src/test/resources/bytesConversions.baseline b/runtime/src/test/resources/bytesConversions.baseline index 4c1458268..6324929ce 100644 --- a/runtime/src/test/resources/bytesConversions.baseline +++ b/runtime/src/test/resources/bytesConversions.baseline @@ -2,3 +2,8 @@ Source: bytes('abc\303') =====> bindings: {} result: abcà + +Source: bytes(bytes('abc\303')) +=====> +bindings: {} +result: abcà \ No newline at end of file diff --git a/runtime/src/test/resources/doubleConversions.baseline b/runtime/src/test/resources/doubleConversions.baseline index d15dfe090..682e56edc 100644 --- a/runtime/src/test/resources/doubleConversions.baseline +++ b/runtime/src/test/resources/doubleConversions.baseline @@ -18,3 +18,8 @@ Source: double('bad') bindings: {} error: evaluation error: For input string: "bad" error_code: BAD_FORMAT + +Source: double(1.5) +=====> +bindings: {} +result: 1.5 \ No newline at end of file diff --git a/runtime/src/test/resources/stringConversions.baseline b/runtime/src/test/resources/stringConversions.baseline index 7e20cff19..59406fc85 100644 --- a/runtime/src/test/resources/stringConversions.baseline +++ b/runtime/src/test/resources/stringConversions.baseline @@ -32,3 +32,8 @@ Source: string(duration('1000000s')) =====> bindings: {} result: 1000000s + +Source: string('hello') +=====> +bindings: {} +result: hello \ No newline at end of file diff --git a/runtime/src/test/resources/timeConversions.baseline b/runtime/src/test/resources/timeConversions.baseline index 18b8fdcb0..cb1c4e886 100644 --- a/runtime/src/test/resources/timeConversions.baseline +++ b/runtime/src/test/resources/timeConversions.baseline @@ -54,3 +54,20 @@ declare t1 { bindings: {} error: evaluation error: invalid duration format error_code: BAD_FORMAT + +Source: duration(duration('15.0s')) +declare t1 { + value google.protobuf.Timestamp +} +=====> +bindings: {} +result: seconds: 15 + + +Source: timestamp(timestamp(123)) +declare t1 { + value google.protobuf.Timestamp +} +=====> +bindings: {} +result: seconds: 123 \ No newline at end of file diff --git a/runtime/src/test/resources/uint64Conversions.baseline b/runtime/src/test/resources/uint64Conversions.baseline index cfdc61974..fac9bfc52 100644 --- a/runtime/src/test/resources/uint64Conversions.baseline +++ b/runtime/src/test/resources/uint64Conversions.baseline @@ -35,3 +35,13 @@ Source: uint('f1') bindings: {} error: evaluation error: f1 error_code: BAD_FORMAT + +Source: uint(1u) +=====> +bindings: {} +result: 1 + +Source: uint(dyn(1u)) +=====> +bindings: {} +result: 1 diff --git a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java index 795145508..3b9d63f11 100644 --- a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java +++ b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java @@ -1261,6 +1261,12 @@ public void timeConversions() throws Exception { // Not supported. source = "duration('inf')"; runTest(Activation.EMPTY); + + source = "duration(duration('15.0s'))"; // Identity + runTest(Activation.EMPTY); + + source = "timestamp(timestamp(123))"; // Identity + runTest(Activation.EMPTY); } @Test @@ -1491,6 +1497,12 @@ public void uint64Conversions() throws Exception { source = "uint('f1')"; // should error runTest(Activation.EMPTY); + + source = "uint(1u)"; // identity + runTest(Activation.EMPTY); + + source = "uint(dyn(1u))"; // identity, check dynamic dispatch + runTest(Activation.EMPTY); } @Test @@ -1506,6 +1518,9 @@ public void doubleConversions() throws Exception { source = "double('bad')"; runTest(Activation.EMPTY); + + source = "double(1.5)"; // Identity + runTest(Activation.EMPTY); } @Test @@ -1536,6 +1551,9 @@ public void stringConversions() throws Exception { source = "string(duration('1000000s'))"; runTest(Activation.EMPTY); + + source = "string('hello')"; // Identity + runTest(Activation.EMPTY); } @Test @@ -1546,10 +1564,19 @@ public void bytes() throws Exception { runTest(Activation.EMPTY); } + @Test + public void boolConversions() throws Exception { + source = "bool(true)"; + runTest(Activation.EMPTY); // Identity + } + @Test public void bytesConversions() throws Exception { source = "bytes('abc\\303')"; runTest(Activation.EMPTY); // string converts to abcà in bytes form. + + source = "bytes(bytes('abc\\303'))"; // Identity + runTest(Activation.EMPTY); } @Test From 4c34530eeef871f74a55cdfabe5967244bd42aeb Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 2 Aug 2024 13:06:41 -0700 Subject: [PATCH 07/33] Add string to boolean conversion function in the standard definition PiperOrigin-RevId: 658882554 --- .../main/java/dev/cel/checker/Standard.java | 4 ++- .../test/resources/standardEnvDump.baseline | 1 + .../dev/cel/runtime/StandardFunctions.java | 27 +++++++++++++++++++ .../test/resources/boolConversions.baseline | 24 ++++++++++++++++- .../dev/cel/testing/BaseInterpreterTest.java | 12 +++++++++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/checker/src/main/java/dev/cel/checker/Standard.java b/checker/src/main/java/dev/cel/checker/Standard.java index eaac8c300..acdc185eb 100644 --- a/checker/src/main/java/dev/cel/checker/Standard.java +++ b/checker/src/main/java/dev/cel/checker/Standard.java @@ -475,7 +475,9 @@ private static ImmutableList coreFunctionDeclarations() { CelFunctionDecl.newFunctionDeclaration( Function.BOOL.getFunction(), CelOverloadDecl.newGlobalOverload( - "bool_to_bool", "type conversion (identity)", SimpleType.BOOL, SimpleType.BOOL))); + "bool_to_bool", "type conversion (identity)", SimpleType.BOOL, SimpleType.BOOL), + CelOverloadDecl.newGlobalOverload( + "string_to_bool", "type conversion", SimpleType.BOOL, SimpleType.STRING))); // String functions celFunctionDeclBuilder.add( diff --git a/checker/src/test/resources/standardEnvDump.baseline b/checker/src/test/resources/standardEnvDump.baseline index 5f88f7f50..df1c66553 100644 --- a/checker/src/test/resources/standardEnvDump.baseline +++ b/checker/src/test/resources/standardEnvDump.baseline @@ -144,6 +144,7 @@ declare _||_ { declare bool { value type(bool) function bool_to_bool (bool) -> bool + function string_to_bool (string) -> bool } declare bytes { value type(bytes) diff --git a/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java b/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java index 23a77c0c7..c69c98271 100644 --- a/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java +++ b/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java @@ -156,6 +156,33 @@ public static void addNonInlined( private static void addBoolFunctions(Registrar registrar) { // Identity registrar.add("bool_to_bool", Boolean.class, (Boolean x) -> x); + // Conversion function + registrar.add( + "string_to_bool", + String.class, + (String str) -> { + // Note: this is a bit less permissive than what cel-go allows (it accepts '1', 't'). + switch (str) { + case "true": + case "TRUE": + case "True": + case "t": + case "1": + return true; + case "false": + case "FALSE": + case "False": + case "f": + case "0": + return false; + default: + throw new InterpreterException.Builder( + "Type conversion error from 'string' to 'bool': [%s]", str) + .setErrorCode(CelErrorCode.BAD_FORMAT) + .build(); + } + }); + // The conditional, logical_or, logical_and, and not_strictly_false functions are special-cased. registrar.add("logical_not", Boolean.class, (Boolean x) -> !x); diff --git a/runtime/src/test/resources/boolConversions.baseline b/runtime/src/test/resources/boolConversions.baseline index 3d7415aba..2bc832baa 100644 --- a/runtime/src/test/resources/boolConversions.baseline +++ b/runtime/src/test/resources/boolConversions.baseline @@ -1,4 +1,26 @@ Source: bool(true) =====> bindings: {} -result: true \ No newline at end of file +result: true + +Source: bool('true') && bool('TRUE') && bool('True') && bool('t') && bool('1') +=====> +bindings: {} +result: true + +Source: bool('false') || bool('FALSE') || bool('False') || bool('f') || bool('0') +=====> +bindings: {} +result: false + +Source: bool('TrUe') +=====> +bindings: {} +error: evaluation error: Type conversion error from 'string' to 'bool': [TrUe] +error_code: BAD_FORMAT + +Source: bool('FaLsE') +=====> +bindings: {} +error: evaluation error: Type conversion error from 'string' to 'bool': [FaLsE] +error_code: BAD_FORMAT diff --git a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java index 3b9d63f11..811af7033 100644 --- a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java +++ b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java @@ -1568,6 +1568,18 @@ public void bytes() throws Exception { public void boolConversions() throws Exception { source = "bool(true)"; runTest(Activation.EMPTY); // Identity + + source = "bool('true') && bool('TRUE') && bool('True') && bool('t') && bool('1')"; + runTest(Activation.EMPTY); // result is true + + source = "bool('false') || bool('FALSE') || bool('False') || bool('f') || bool('0')"; + runTest(Activation.EMPTY); // result is false + + source = "bool('TrUe')"; + runTest(Activation.EMPTY); // exception + + source = "bool('FaLsE')"; + runTest(Activation.EMPTY); // exception } @Test From eba4c270e5cbc27e318d9f244e148ebb79e60b6e Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 2 Aug 2024 14:29:25 -0700 Subject: [PATCH 08/33] Upgrade protobuf version to 4.27.3 PiperOrigin-RevId: 658906809 --- WORKSPACE | 28 +++++++++++++------ .../src/main/java/dev/cel/bundle/BUILD.bazel | 2 +- .../src/test/java/dev/cel/bundle/BUILD.bazel | 5 ++-- .../src/main/java/dev/cel/checker/BUILD.bazel | 10 +++---- .../src/test/java/dev/cel/checker/BUILD.bazel | 4 +-- codelab/src/main/codelab/BUILD.bazel | 4 +-- .../src/main/codelab/solutions/BUILD.bazel | 4 +-- codelab/src/test/codelab/BUILD.bazel | 16 +++++------ .../src/test/codelab/solutions/BUILD.bazel | 16 +++++------ .../src/main/java/dev/cel/common/BUILD.bazel | 4 +-- .../main/java/dev/cel/common/ast/BUILD.bazel | 4 +-- .../java/dev/cel/common/internal/BUILD.bazel | 18 ++++++------ .../java/dev/cel/common/types/BUILD.bazel | 6 ++-- .../java/dev/cel/common/values/BUILD.bazel | 4 +-- .../src/test/java/dev/cel/common/BUILD.bazel | 4 +-- .../test/java/dev/cel/common/ast/BUILD.bazel | 2 +- .../java/dev/cel/common/internal/BUILD.bazel | 4 +-- .../java/dev/cel/common/values/BUILD.bazel | 2 +- .../main/java/dev/cel/compiler/BUILD.bazel | 4 +-- .../main/java/dev/cel/extensions/BUILD.bazel | 4 +-- .../test/java/dev/cel/extensions/BUILD.bazel | 2 +- .../src/main/java/dev/cel/parser/BUILD.bazel | 2 +- .../src/test/java/dev/cel/parser/BUILD.bazel | 2 +- .../src/test/java/dev/cel/policy/BUILD.bazel | 2 +- .../src/main/java/dev/cel/runtime/BUILD.bazel | 8 +++--- .../src/test/java/dev/cel/runtime/BUILD.bazel | 4 +-- .../src/main/java/dev/cel/testing/BUILD.bazel | 10 +++---- .../src/test/java/dev/cel/testing/BUILD.bazel | 4 +-- .../dev/cel/validator/validators/BUILD.bazel | 4 +-- .../dev/cel/validator/validators/BUILD.bazel | 2 +- 30 files changed, 98 insertions(+), 87 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 09fdb0443..798ad38c8 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -20,10 +20,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_jar") http_archive( name = "bazel_skylib", - sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506", + sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz", ], ) @@ -31,6 +31,18 @@ load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() +# Transitive dependency required by protobuf v4 https://github.com/protocolbuffers/protobuf/issues/17200 +http_archive( + name = "rules_python", + sha256 = "778aaeab3e6cfd56d681c89f5c10d7ad6bf8d2f1a72de9de55b23081b2d31618", + strip_prefix = "rules_python-0.34.0", + url = "https://github.com/bazelbuild/rules_python/releases/download/0.34.0/rules_python-0.34.0.tar.gz", +) + +load("@rules_python//python:repositories.bzl", "py_repositories") + +py_repositories() + RULES_JVM_EXTERNAL_TAG = "aa44247b3913da0da606e9c522313b6a9396a571" RULES_JVM_EXTERNAL_SHA = "87378580865af690a78230e04eba1cd6d9c60d0db303ea129dc717705d711d9c" @@ -58,15 +70,13 @@ ANTLR4_VERSION = "4.13.1" maven_install( # keep sorted artifacts = [ - "com.google.api.grpc:proto-google-common-protos:2.38.0", "com.google.auto.value:auto-value:1.10.4", "com.google.auto.value:auto-value-annotations:1.10.4", "com.google.code.findbugs:annotations:3.0.1", "com.google.errorprone:error_prone_annotations:2.26.1", "com.google.guava:guava:33.1.0-jre", "com.google.guava:guava-testlib:33.1.0-jre", - "com.google.protobuf:protobuf-java:3.25.3", - "com.google.protobuf:protobuf-java-util:3.25.3", + "com.google.protobuf:protobuf-java-util:4.27.3", "com.google.re2j:re2j:1.7", "com.google.testparameterinjector:test-parameter-injector:1.15", "com.google.truth.extensions:truth-java8-extension:1.4.2", @@ -85,9 +95,9 @@ maven_install( http_archive( name = "com_google_protobuf", - sha256 = "b1d6dd2cbb5d87e17af41cadb720322ce7e13af826268707bd8db47e5654770b", - strip_prefix = "protobuf-21.11", - urls = ["https://github.com/protocolbuffers/protobuf/archive/v21.11.tar.gz"], + sha256 = "1535151efbc7893f38b0578e83cac584f2819974f065698976989ec71c1af84a", + strip_prefix = "protobuf-27.3", + urls = ["https://github.com/protocolbuffers/protobuf/archive/v27.3.tar.gz"], ) # Required by com_google_protobuf diff --git a/bundle/src/main/java/dev/cel/bundle/BUILD.bazel b/bundle/src/main/java/dev/cel/bundle/BUILD.bazel index c2c7d3f10..70744129c 100644 --- a/bundle/src/main/java/dev/cel/bundle/BUILD.bazel +++ b/bundle/src/main/java/dev/cel/bundle/BUILD.bazel @@ -37,10 +37,10 @@ java_library( "//parser:macro", "//parser:parser_builder", "//runtime", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/bundle/src/test/java/dev/cel/bundle/BUILD.bazel b/bundle/src/test/java/dev/cel/bundle/BUILD.bazel index cccfc8eed..f19406eec 100644 --- a/bundle/src/test/java/dev/cel/bundle/BUILD.bazel +++ b/bundle/src/test/java/dev/cel/bundle/BUILD.bazel @@ -36,11 +36,12 @@ java_library( "//parser:macro", "//runtime", "//runtime:unknown_attributes", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", + "@com_google_googleapis//google/type:type_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_guava_guava_testlib", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:com_google_truth_extensions_truth_proto_extension", diff --git a/checker/src/main/java/dev/cel/checker/BUILD.bazel b/checker/src/main/java/dev/cel/checker/BUILD.bazel index 0053d9061..039eb7f6c 100644 --- a/checker/src/main/java/dev/cel/checker/BUILD.bazel +++ b/checker/src/main/java/dev/cel/checker/BUILD.bazel @@ -50,10 +50,10 @@ java_library( "//common/types", "//common/types:cel_types", "//common/types:type_providers", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) @@ -81,10 +81,10 @@ java_library( "//common/types:cel_types", "//common/types:message_type_provider", "//common/types:type_providers", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -100,9 +100,9 @@ java_library( "//common:compiler_common", "//common:options", "//common/types:type_providers", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -113,9 +113,9 @@ java_library( ], deps = [ "//:auto_value", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -180,10 +180,10 @@ java_library( "//common/types:type_providers", "//parser:macro", "//parser:operator", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) diff --git a/checker/src/test/java/dev/cel/checker/BUILD.bazel b/checker/src/test/java/dev/cel/checker/BUILD.bazel index 338dcbb10..52a39a8ae 100644 --- a/checker/src/test/java/dev/cel/checker/BUILD.bazel +++ b/checker/src/test/java/dev/cel/checker/BUILD.bazel @@ -10,6 +10,7 @@ java_library( srcs = glob(["*Test.java"]), resources = ["//checker/src/test/resources:baselines"], deps = [ + "@@protobuf~//java/core", # "//java/com/google/testing/testsize:annotations", "//:auto_value", "//checker", @@ -48,9 +49,8 @@ java_library( "//:java_truth", "@maven//:com_google_truth_extensions_truth_proto_extension", "@cel_spec//proto/cel/expr:expr_java_proto", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/codelab/src/main/codelab/BUILD.bazel b/codelab/src/main/codelab/BUILD.bazel index 6c9f90259..7b3065e47 100644 --- a/codelab/src/main/codelab/BUILD.bazel +++ b/codelab/src/main/codelab/BUILD.bazel @@ -33,9 +33,9 @@ java_library( "//validator/validators:homogeneous_literal", # unuseddeps: keep "//validator/validators:regex", # unuseddeps: keep "//validator/validators:timestamp", # unuseddeps: keep - "@maven//:com_google_api_grpc_proto_google_common_protos", # unuseddeps: keep + "@@protobuf~//java/core", # unuseddeps: keep + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", # unuseddeps: keep "@maven//:com_google_guava_guava", # unuseddeps: keep - "@maven//:com_google_protobuf_protobuf_java", # unuseddeps: keep "@maven//:com_google_protobuf_protobuf_java_util", # unuseddeps: keep ], ) diff --git a/codelab/src/main/codelab/solutions/BUILD.bazel b/codelab/src/main/codelab/solutions/BUILD.bazel index 44f9632ea..42820a846 100644 --- a/codelab/src/main/codelab/solutions/BUILD.bazel +++ b/codelab/src/main/codelab/solutions/BUILD.bazel @@ -33,9 +33,9 @@ java_library( "//validator/validators:homogeneous_literal", "//validator/validators:regex", "//validator/validators:timestamp", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", ], ) diff --git a/codelab/src/test/codelab/BUILD.bazel b/codelab/src/test/codelab/BUILD.bazel index 8772578c1..84363646a 100644 --- a/codelab/src/test/codelab/BUILD.bazel +++ b/codelab/src/test/codelab/BUILD.bazel @@ -27,9 +27,9 @@ java_test( "//codelab", "//common", "//common/types", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], @@ -58,9 +58,9 @@ java_test( "//:java_truth", "//codelab", "//common", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], @@ -91,9 +91,9 @@ java_test( "//:java_truth", "//codelab", "//common", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", @@ -127,7 +127,7 @@ java_test( "//common:compiler_common", "//parser:unparser", "//runtime", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", @@ -144,7 +144,7 @@ java_test( "//codelab", "//common", "//common:compiler_common", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], diff --git a/codelab/src/test/codelab/solutions/BUILD.bazel b/codelab/src/test/codelab/solutions/BUILD.bazel index 0ac187a92..be146d8f9 100644 --- a/codelab/src/test/codelab/solutions/BUILD.bazel +++ b/codelab/src/test/codelab/solutions/BUILD.bazel @@ -25,9 +25,9 @@ java_test( "//codelab:solutions", "//common", "//common/types", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], @@ -54,9 +54,9 @@ java_test( "//:java_truth", "//codelab:solutions", "//common", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], @@ -85,9 +85,9 @@ java_test( "//:java_truth", "//codelab:solutions", "//common", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", @@ -119,7 +119,7 @@ java_test( "//common:compiler_common", "//parser:unparser", "//runtime", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", @@ -135,7 +135,7 @@ java_test( "//codelab:solutions", "//common", "//common:compiler_common", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], diff --git a/common/src/main/java/dev/cel/common/BUILD.bazel b/common/src/main/java/dev/cel/common/BUILD.bazel index dbb8890d5..4706fb93d 100644 --- a/common/src/main/java/dev/cel/common/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/BUILD.bazel @@ -55,10 +55,10 @@ java_library( "//common/types", "//common/types:cel_types", "//common/types:type_providers", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -178,9 +178,9 @@ java_library( tags = [ ], deps = [ + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", ], ) diff --git a/common/src/main/java/dev/cel/common/ast/BUILD.bazel b/common/src/main/java/dev/cel/common/ast/BUILD.bazel index c59178bcd..6c1709f1a 100644 --- a/common/src/main/java/dev/cel/common/ast/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/ast/BUILD.bazel @@ -46,9 +46,9 @@ java_library( deps = [ "//:auto_value", "//common/annotations", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) @@ -96,8 +96,8 @@ java_library( deps = [ ":ast", "//common/annotations", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/common/src/main/java/dev/cel/common/internal/BUILD.bazel b/common/src/main/java/dev/cel/common/internal/BUILD.bazel index 0ea165ae1..70a91fc8c 100644 --- a/common/src/main/java/dev/cel/common/internal/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/internal/BUILD.bazel @@ -40,9 +40,9 @@ java_library( "//:auto_value", "//common/annotations", "//common/ast", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_antlr_antlr4_runtime", ], ) @@ -103,8 +103,8 @@ java_library( ], deps = [ "//common/annotations", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -124,11 +124,11 @@ java_library( "//common:proto_json_adapter", "//common:runtime_exception", "//common/annotations", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) @@ -142,9 +142,9 @@ java_library( ":dynamic_proto", "//:auto_value", "//common/annotations", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) @@ -158,9 +158,9 @@ java_library( ], deps = [ "//:auto_value", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -182,8 +182,8 @@ java_library( ], deps = [ "//common/annotations", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -197,7 +197,7 @@ java_library( ":default_instance_message_factory", ":proto_message_factory", "//common/annotations", - "@maven//:com_google_protobuf_protobuf_java", + "@@protobuf~//java/core", ], ) @@ -208,9 +208,9 @@ java_library( ], deps = [ ":cel_descriptor_pools", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -223,9 +223,9 @@ java_library( ":well_known_proto", "//common", "//common/annotations", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/common/src/main/java/dev/cel/common/types/BUILD.bazel b/common/src/main/java/dev/cel/common/types/BUILD.bazel index 1a3f3ca0d..19c741e0f 100644 --- a/common/src/main/java/dev/cel/common/types/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/types/BUILD.bazel @@ -73,9 +73,9 @@ java_library( ":type_providers", ":types", "//common/annotations", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -88,9 +88,9 @@ java_library( ":type_providers", ":types", "//common/annotations", + "@@protobuf~//java/core", "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -132,8 +132,8 @@ java_library( "//:auto_value", "//common", "//common/internal:file_descriptor_converter", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/common/src/main/java/dev/cel/common/values/BUILD.bazel b/common/src/main/java/dev/cel/common/values/BUILD.bazel index 766e22309..fcb1269fa 100644 --- a/common/src/main/java/dev/cel/common/values/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/values/BUILD.bazel @@ -114,9 +114,9 @@ java_library( "//common/types:cel_types", "//common/types:type_providers", "//common/values:cel_byte_string", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:org_jspecify_jspecify", ], @@ -137,7 +137,7 @@ java_library( "//common/annotations", "//common/internal:dynamic_proto", "//common/internal:proto_message_factory", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/common/src/test/java/dev/cel/common/BUILD.bazel b/common/src/test/java/dev/cel/common/BUILD.bazel index e7ca691ed..f5c08b3b4 100644 --- a/common/src/test/java/dev/cel/common/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/BUILD.bazel @@ -21,11 +21,11 @@ java_library( "//common/types", "//common/types:cel_types", "//common/types:cel_v1alpha1_types", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:com_google_truth_extensions_truth_proto_extension", "@maven//:junit_junit", diff --git a/common/src/test/java/dev/cel/common/ast/BUILD.bazel b/common/src/test/java/dev/cel/common/ast/BUILD.bazel index 61e6beb11..3f1868156 100644 --- a/common/src/test/java/dev/cel/common/ast/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/ast/BUILD.bazel @@ -29,11 +29,11 @@ java_library( "//extensions:optional_library", "//parser:macro", "//parser:operator", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_guava_guava_testlib", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], diff --git a/common/src/test/java/dev/cel/common/internal/BUILD.bazel b/common/src/test/java/dev/cel/common/internal/BUILD.bazel index af0a673aa..5109b23ac 100644 --- a/common/src/test/java/dev/cel/common/internal/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/internal/BUILD.bazel @@ -34,9 +34,9 @@ java_library( "//common/src/test/resources:service_conflicting_name_java_proto", "//common/src/test/resources:single_file_java_proto", "//common/testing", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/type:type_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], diff --git a/common/src/test/java/dev/cel/common/values/BUILD.bazel b/common/src/test/java/dev/cel/common/values/BUILD.bazel index 5b3ac349c..388e4d6fb 100644 --- a/common/src/test/java/dev/cel/common/values/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/values/BUILD.bazel @@ -27,9 +27,9 @@ java_library( "//common/values:cel_value_provider", "//common/values:proto_message_value", "//common/values:proto_message_value_provider", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", "@maven//:com_google_guava_guava_testlib", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", diff --git a/compiler/src/main/java/dev/cel/compiler/BUILD.bazel b/compiler/src/main/java/dev/cel/compiler/BUILD.bazel index fc20e8170..1f58aafe9 100644 --- a/compiler/src/main/java/dev/cel/compiler/BUILD.bazel +++ b/compiler/src/main/java/dev/cel/compiler/BUILD.bazel @@ -42,10 +42,10 @@ java_library( "//parser", "//parser:macro", "//parser:parser_builder", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -64,8 +64,8 @@ java_library( "//common/types:type_providers", "//parser:macro", "//parser:parser_builder", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel index 9cf66cf1e..a6e35911d 100644 --- a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel @@ -101,9 +101,9 @@ java_library( "//common/types", "//compiler:compiler_builder", "//runtime", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -124,8 +124,8 @@ java_library( "//parser:operator", "//parser:parser_builder", "//runtime", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) diff --git a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel index 1edea7cb0..6cfbe3381 100644 --- a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel @@ -28,9 +28,9 @@ java_library( "//parser:macro", "//runtime", "//runtime:interpreter_util", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", diff --git a/parser/src/main/java/dev/cel/parser/BUILD.bazel b/parser/src/main/java/dev/cel/parser/BUILD.bazel index f49628e34..e3d13b92b 100644 --- a/parser/src/main/java/dev/cel/parser/BUILD.bazel +++ b/parser/src/main/java/dev/cel/parser/BUILD.bazel @@ -123,6 +123,6 @@ java_library( "//common", "//common/ast", "//common/ast:cel_expr_visitor", - "@maven//:com_google_protobuf_protobuf_java", + "@@protobuf~//java/core", ], ) diff --git a/parser/src/test/java/dev/cel/parser/BUILD.bazel b/parser/src/test/java/dev/cel/parser/BUILD.bazel index 270c412c5..fe29d5d43 100644 --- a/parser/src/test/java/dev/cel/parser/BUILD.bazel +++ b/parser/src/test/java/dev/cel/parser/BUILD.bazel @@ -25,11 +25,11 @@ java_library( "//parser:unparser", "//testing:adorner", "//testing:baseline_test_case", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven//:com_google_guava_guava_testlib", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], diff --git a/policy/src/test/java/dev/cel/policy/BUILD.bazel b/policy/src/test/java/dev/cel/policy/BUILD.bazel index 8606ca254..4ae85cb55 100644 --- a/policy/src/test/java/dev/cel/policy/BUILD.bazel +++ b/policy/src/test/java/dev/cel/policy/BUILD.bazel @@ -32,7 +32,7 @@ java_library( "//policy:validation_exception", "//policy:value_string", "//runtime", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", diff --git a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel index f51706987..20031fc22 100644 --- a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel @@ -54,10 +54,10 @@ java_library( "//common/internal:safe_string_formatter", "//common/types", "//common/types:type_providers", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_re2j_re2j", "@maven//:org_jspecify_jspecify", @@ -90,11 +90,11 @@ java_library( "//common/internal:proto_message_factory", "//common/types:cel_types", "//common/types:type_providers", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) @@ -117,9 +117,9 @@ java_library( "//common/internal:converter", "//common/internal:dynamic_proto", "//common/internal:proto_equality", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_re2j_re2j", "@maven//:org_threeten_threeten_extra", ], @@ -160,10 +160,10 @@ java_library( "//common/values:cel_value_provider", "//common/values:proto_message_value_provider", "//runtime:interpreter", + "@@protobuf~//java/core", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:org_jspecify_jspecify", ], ) diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel index fea8d6e43..dd188ea28 100644 --- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel @@ -43,10 +43,10 @@ java_library( "//runtime:runtime_helper", "//runtime:unknown_attributes", "//runtime:unknown_options", + "@@protobuf~//java/core", "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:com_google_truth_extensions_truth_proto_extension", diff --git a/testing/src/main/java/dev/cel/testing/BUILD.bazel b/testing/src/main/java/dev/cel/testing/BUILD.bazel index 7e4c69fb9..4643e1272 100644 --- a/testing/src/main/java/dev/cel/testing/BUILD.bazel +++ b/testing/src/main/java/dev/cel/testing/BUILD.bazel @@ -75,9 +75,9 @@ java_library( "//compiler", "//compiler:compiler_builder", "//parser:macro", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -97,8 +97,8 @@ java_library( "//common/values:proto_message_value_provider", "//runtime:interpreter", "//runtime:runtime_type_provider_legacy", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -113,8 +113,8 @@ java_library( "//common/internal:cel_descriptor_pools", "//common/internal:default_message_factory", "//runtime:interpreter", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -129,9 +129,9 @@ java_library( "//common:options", "//runtime:base", "//runtime:interpreter", + "@@protobuf~//java/core", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -156,10 +156,10 @@ java_library( "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types:cel_types", "//runtime:interpreter", + "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:junit_junit", ], diff --git a/testing/src/test/java/dev/cel/testing/BUILD.bazel b/testing/src/test/java/dev/cel/testing/BUILD.bazel index 4d4a12ec4..6e4980c8a 100644 --- a/testing/src/test/java/dev/cel/testing/BUILD.bazel +++ b/testing/src/test/java/dev/cel/testing/BUILD.bazel @@ -21,9 +21,9 @@ java_library( "//runtime:interpreter", "//testing:line_differ", "//testing:sync", - "@maven//:com_google_api_grpc_proto_google_common_protos", + "@@protobuf~//java/core", + "@com_google_googleapis//google/type:type_java_proto", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:junit_junit", ], ) diff --git a/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel b/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel index e9c07fb10..d049a3659 100644 --- a/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel +++ b/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel @@ -15,7 +15,7 @@ java_library( ], deps = [ ":literal_validator", - "@maven//:com_google_protobuf_protobuf_java", + "@@protobuf~//java/core", ], ) @@ -28,7 +28,7 @@ java_library( ], deps = [ ":literal_validator", - "@maven//:com_google_protobuf_protobuf_java", + "@@protobuf~//java/core", ], ) diff --git a/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel b/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel index eca252aa9..1f8af4661 100644 --- a/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel +++ b/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel @@ -21,8 +21,8 @@ java_library( "//validator/validators:homogeneous_literal", "//validator/validators:regex", "//validator/validators:timestamp", + "@@protobuf~//java/core", "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", From 8fe0b7f7fec09eae59202c809fff749992a06a6f Mon Sep 17 00:00:00 2001 From: CEL Dev Team Date: Thu, 8 Aug 2024 09:54:23 -0700 Subject: [PATCH 09/33] No public description PiperOrigin-RevId: 660876414 --- .../dev/cel/common/navigation/ExprPropertyCalculator.java | 4 ++-- policy/src/main/java/dev/cel/policy/CelPolicyConfig.java | 6 +++--- policy/src/main/java/dev/cel/policy/RuleComposer.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/dev/cel/common/navigation/ExprPropertyCalculator.java b/common/src/main/java/dev/cel/common/navigation/ExprPropertyCalculator.java index c90c1f2f9..be2c07221 100644 --- a/common/src/main/java/dev/cel/common/navigation/ExprPropertyCalculator.java +++ b/common/src/main/java/dev/cel/common/navigation/ExprPropertyCalculator.java @@ -140,9 +140,9 @@ private ExprProperty visitExprList(java.util.List list) { /** Value class to store the height and the max ID at a specific expression ID. */ @AutoValue abstract static class ExprProperty { - abstract Integer height(); + abstract int height(); - abstract Long maxId(); + abstract long maxId(); /** Merges the two {@link ExprProperty}, taking their maximum values from the properties. */ private static ExprProperty merge(ExprProperty e1, ExprProperty e2) { diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java b/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java index d3786d512..cf6ca3ec3 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java @@ -369,7 +369,7 @@ public abstract static class TypeDecl { public abstract ImmutableList params(); - public abstract Boolean isTypeParam(); + public abstract boolean isTypeParam(); /** Builder for {@link TypeDecl}. */ @AutoValue.Builder @@ -474,7 +474,7 @@ public abstract static class ExtensionConfig { * Version of the extension. Presently, this field is ignored as CEL-Java extensions are not * versioned. */ - public abstract Integer version(); + public abstract int version(); /** Builder for {@link ExtensionConfig}. */ @AutoValue.Builder @@ -486,7 +486,7 @@ public abstract static class Builder implements RequiredFieldsChecker { public abstract Builder setName(String name); - public abstract Builder setVersion(Integer version); + public abstract Builder setVersion(int version); @Override public ImmutableList requiredFields() { diff --git a/policy/src/main/java/dev/cel/policy/RuleComposer.java b/policy/src/main/java/dev/cel/policy/RuleComposer.java index c3b888887..42b1b7af2 100644 --- a/policy/src/main/java/dev/cel/policy/RuleComposer.java +++ b/policy/src/main/java/dev/cel/policy/RuleComposer.java @@ -52,7 +52,7 @@ public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) { abstract static class RuleOptimizationResult { abstract CelMutableAst ast(); - abstract Boolean isOptionalResult(); + abstract boolean isOptionalResult(); static RuleOptimizationResult create(CelMutableAst ast, boolean isOptionalResult) { return new AutoValue_RuleComposer_RuleOptimizationResult(ast, isOptionalResult); From 06dec78bf83e13e3cb0c7e659b323909e137c56a Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 9 Aug 2024 10:27:25 -0700 Subject: [PATCH 10/33] Provide an overload to hide all fields on a message with ProtoTypeMask PiperOrigin-RevId: 661315262 --- .../test/java/dev/cel/bundle/CelImplTest.java | 47 +++++++++++++++++++ .../java/dev/cel/checker/ProtoTypeMask.java | 22 +++++++++ .../checker/ProtoTypeMaskTypeProvider.java | 9 +++- .../dev/cel/checker/ProtoTypeMaskTest.java | 8 ++++ .../ProtoTypeMaskTypeProviderTest.java | 40 +++++++++++++++- 5 files changed, 122 insertions(+), 4 deletions(-) diff --git a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java index ef751df18..ecbac380e 100644 --- a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java +++ b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java @@ -579,6 +579,53 @@ public void program_withProtoVars() throws Exception { .isEqualTo(true); } + @Test + public void program_withAllFieldsHidden_emptyMessageConstructionSuccess() throws Exception { + Cel cel = + standardCelBuilderWithMacros() + .addMessageTypes(AttributeContext.getDescriptor()) + .setContainer("google.rpc.context.AttributeContext") + .addProtoTypeMasks( + ProtoTypeMask.ofAllFieldsHidden("google.rpc.context.AttributeContext")) + .build(); + + assertThat(cel.createProgram(cel.compile("AttributeContext{}").getAst()).eval()) + .isEqualTo(AttributeContext.getDefaultInstance()); + } + + @Test + public void compile_withAllFieldsHidden_selectHiddenField_throws() throws Exception { + Cel cel = + standardCelBuilderWithMacros() + .addMessageTypes(AttributeContext.getDescriptor()) + .setContainer("google.rpc.context.AttributeContext") + .addProtoTypeMasks( + ProtoTypeMask.ofAllFieldsHidden("google.rpc.context.AttributeContext")) + .build(); + + CelValidationException e = + assertThrows( + CelValidationException.class, + () -> cel.compile("AttributeContext{ request: AttributeContext.Request{} }").getAst()); + assertThat(e).hasMessageThat().contains("undefined field 'request'"); + } + + @Test + public void compile_withAllFieldsHidden_selectHiddenFieldOnVar_throws() throws Exception { + Cel cel = + standardCelBuilderWithMacros() + .addMessageTypes(AttributeContext.getDescriptor()) + .setContainer("google.rpc.context.AttributeContext") + .addProtoTypeMasks( + ProtoTypeMask.ofAllFieldsHidden("google.rpc.context.AttributeContext")) + .addVar("attr_ctx", StructTypeReference.create("google.rpc.context.AttributeContext")) + .build(); + + CelValidationException e = + assertThrows(CelValidationException.class, () -> cel.compile("attr_ctx.source").getAst()); + assertThat(e).hasMessageThat().contains("undefined field 'source'"); + } + @Test public void program_withNestedRestrictedProtoVars() throws Exception { Cel cel = diff --git a/checker/src/main/java/dev/cel/checker/ProtoTypeMask.java b/checker/src/main/java/dev/cel/checker/ProtoTypeMask.java index 1a129a91f..c019604d5 100644 --- a/checker/src/main/java/dev/cel/checker/ProtoTypeMask.java +++ b/checker/src/main/java/dev/cel/checker/ProtoTypeMask.java @@ -38,6 +38,13 @@ public abstract class ProtoTypeMask { /** WILDCARD_FIELD indicates that all fields within the proto type are visible. */ static final String WILDCARD_FIELD = "*"; + /** HIDDEN_FIELD indicates that all fields within the proto type are not visible. */ + static final String HIDDEN_FIELD = "!"; + + private static final FieldMask HIDDEN_FIELD_MASK = + FieldMask.newBuilder().addPaths(HIDDEN_FIELD).build(); + + private static final FieldPath HIDDEN_FIELD_PATH = FieldPath.of(HIDDEN_FIELD); private static final FieldMask WILDCARD_FIELD_MASK = FieldMask.newBuilder().addPaths(WILDCARD_FIELD).build(); private static final FieldPath WILDCARD_FIELD_PATH = FieldPath.of(WILDCARD_FIELD); @@ -52,6 +59,10 @@ boolean areAllFieldPathsExposed() { return getFieldPathsExposed().stream().allMatch(fp -> fp.equals(WILDCARD_FIELD_PATH)); } + boolean areAllFieldPathsHidden() { + return getFieldPathsExposed().stream().allMatch(fp -> fp.equals(HIDDEN_FIELD_PATH)); + } + public ProtoTypeMask withFieldsAsVariableDeclarations() { return new AutoValue_ProtoTypeMask(getTypeName(), getFieldPathsExposed(), true); } @@ -98,6 +109,17 @@ public static ProtoTypeMask ofAllFields(String fullyQualifiedTypeName) { return of(fullyQualifiedTypeName, WILDCARD_FIELD_MASK); } + /** + * Construct a new {@code ProtoTypeMask} which hides all fields in the given {@code typeName} for + * use within CEL expressions. + * + *

The {@code typeName} should be a fully-qualified path, e.g., {@code + * "google.rpc.context.AttributeContext"}. + */ + public static ProtoTypeMask ofAllFieldsHidden(String fullyQualifiedTypeName) { + return of(fullyQualifiedTypeName, HIDDEN_FIELD_MASK); + } + /** * FieldPath is the equivalent of a field selection represented within a {@link FieldMask#path}. */ diff --git a/checker/src/main/java/dev/cel/checker/ProtoTypeMaskTypeProvider.java b/checker/src/main/java/dev/cel/checker/ProtoTypeMaskTypeProvider.java index 61511c38d..025dfaf1a 100644 --- a/checker/src/main/java/dev/cel/checker/ProtoTypeMaskTypeProvider.java +++ b/checker/src/main/java/dev/cel/checker/ProtoTypeMaskTypeProvider.java @@ -92,11 +92,16 @@ private static ImmutableMap computeVisibleFieldsMap( CelTypeProvider delegateProvider, ImmutableSet protoTypeMasks) { Map> fieldMap = new HashMap<>(); for (ProtoTypeMask typeMask : protoTypeMasks) { - Optional rootType = delegateProvider.findType(typeMask.getTypeName()); - checkArgument(rootType.isPresent(), "message not registered: %s", typeMask.getTypeName()); + String typeName = typeMask.getTypeName(); + Optional rootType = delegateProvider.findType(typeName); + checkArgument(rootType.isPresent(), "message not registered: %s", typeName); if (typeMask.areAllFieldPathsExposed()) { continue; } + if (typeMask.areAllFieldPathsHidden()) { + fieldMap.put(typeName, ImmutableSet.of()); + continue; + } // Unroll the type(messageType) to just messageType. CelType type = rootType.get(); checkArgument(type instanceof ProtoMessageType, "type is not a protobuf: %s", type.name()); diff --git a/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTest.java b/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTest.java index f937dbdc2..89241652c 100644 --- a/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTest.java +++ b/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTest.java @@ -85,6 +85,14 @@ public void ofTypeWithFieldMask_invalidMask() { () -> ProtoTypeMask.of("test", FieldMask.newBuilder().addPaths("").build())); } + @Test + public void ofAllFieldsHidden() { + ProtoTypeMask typeExpr = ProtoTypeMask.ofAllFieldsHidden("google.rpc.context.AttributeContext"); + assertThat(typeExpr.areAllFieldPathsExposed()).isFalse(); + assertThat(typeExpr.getFieldPathsExposed()) + .containsExactly(FieldPath.of(ProtoTypeMask.HIDDEN_FIELD)); + } + @Test public void withFieldsAsVariableDeclarations() { assertThat(ProtoTypeMask.ofAllFields("google.type.Expr").fieldsAreVariableDeclarations()) diff --git a/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTypeProviderTest.java b/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTypeProviderTest.java index bf41c1e20..b4b52bd26 100644 --- a/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTypeProviderTest.java +++ b/checker/src/test/java/dev/cel/checker/ProtoTypeMaskTypeProviderTest.java @@ -28,6 +28,7 @@ import dev.cel.common.types.ProtoMessageType; import dev.cel.common.types.ProtoMessageTypeProvider; import dev.cel.common.types.SimpleType; +import dev.cel.common.types.StructType.Field; import java.util.Arrays; import java.util.Optional; import org.junit.Test; @@ -72,7 +73,7 @@ public void lookupFieldNames_noProtoDecls() { ProtoTypeMaskTypeProvider protoTypeMaskProvider = new ProtoTypeMaskTypeProvider(celTypeProvider, ImmutableSet.of()); ProtoMessageType protoType = assertTypeFound(protoTypeMaskProvider, ATTRIBUTE_CONTEXT_TYPE); - assertThat(protoType.fields().stream().map(f -> f.name()).collect(toImmutableList())) + assertThat(protoType.fields().stream().map(Field::name).collect(toImmutableList())) .containsExactly( "resource", "request", @@ -87,6 +88,41 @@ public void lookupFieldNames_noProtoDecls() { assertThat(protoType).isSameInstanceAs(origProtoType); } + @Test + public void lookupFieldNames_allFieldsHidden() { + CelTypeProvider celTypeProvider = + new ProtoMessageTypeProvider(ImmutableSet.of(AttributeContext.getDescriptor())); + ProtoTypeMaskTypeProvider protoTypeMaskProvider = + new ProtoTypeMaskTypeProvider( + celTypeProvider, + ImmutableSet.of(ProtoTypeMask.ofAllFieldsHidden(ATTRIBUTE_CONTEXT_TYPE))); + + ProtoMessageType protoType = assertTypeFound(protoTypeMaskProvider, ATTRIBUTE_CONTEXT_TYPE); + assertThat(protoType.fieldNames()).isEmpty(); + ProtoMessageType origProtoType = assertTypeFound(celTypeProvider, ATTRIBUTE_CONTEXT_TYPE); + assertThat(protoType).isNotSameInstanceAs(origProtoType); + } + + @Test + public void protoTypeMaskProvider_hiddenFieldSentinelCharOnSubPath_throws() { + CelTypeProvider celTypeProvider = + new ProtoMessageTypeProvider(ImmutableSet.of(AttributeContext.getDescriptor())); + + IllegalArgumentException e = + assertThrows( + IllegalArgumentException.class, + () -> + new ProtoTypeMaskTypeProvider( + celTypeProvider, + ImmutableSet.of( + ProtoTypeMask.of( + "google.rpc.context.AttributeContext", + FieldMask.newBuilder().addPaths("resource.!").build())))); + assertThat(e) + .hasMessageThat() + .contains("message google.rpc.context.AttributeContext.Resource does not declare field: !"); + } + @Test public void lookupFieldNames_fullProtoDecl() { CelTypeProvider celTypeProvider = @@ -263,7 +299,7 @@ private ProtoMessageType assertTypeFound(CelTypeProvider celTypeProvider, String private void assertTypeHasFields(ProtoMessageType protoType, ImmutableSet fields) { ImmutableSet typeFieldNames = - protoType.fields().stream().map(f -> f.name()).collect(toImmutableSet()); + protoType.fields().stream().map(Field::name).collect(toImmutableSet()); assertThat(typeFieldNames).containsExactlyElementsIn(fields); } From 8073b79e02c21a6f934818017054c29ae22d6240 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Mon, 12 Aug 2024 09:56:10 -0700 Subject: [PATCH 11/33] Open source Java conformance tests PiperOrigin-RevId: 662127834 --- .github/workflows/workflow.yml | 4 +- WORKSPACE | 6 +- .../dev/cel/checker/CelProtoExprVisitor.java | 2 +- .../common/CelProtoAbstractSyntaxTree.java | 12 +- .../dev/cel/common/internal/Constants.java | 2 +- .../DefaultInstanceMessageFactory.java | 4 +- .../test/java/dev/cel/conformance/BUILD.bazel | 152 +++++++ .../dev/cel/conformance/ConformanceTest.java | 408 ++++++++++++++++++ .../conformance/ConformanceTestRunner.java | 128 ++++++ .../dev/cel/conformance/ConformanceTests.java | 20 + .../dev/cel/conformance/conformance_test.bzl | 80 ++++ .../dev/cel/conformance/conformance_test.sh | 8 + .../main/java/dev/cel/testing/CelDebug.java | 4 +- 13 files changed, 814 insertions(+), 16 deletions(-) create mode 100644 conformance/src/test/java/dev/cel/conformance/BUILD.bazel create mode 100644 conformance/src/test/java/dev/cel/conformance/ConformanceTest.java create mode 100644 conformance/src/test/java/dev/cel/conformance/ConformanceTestRunner.java create mode 100644 conformance/src/test/java/dev/cel/conformance/ConformanceTests.java create mode 100644 conformance/src/test/java/dev/cel/conformance/conformance_test.bzl create mode 100755 conformance/src/test/java/dev/cel/conformance/conformance_test.sh diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 16ebd2a5f..4cf231b27 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -32,5 +32,7 @@ jobs: - name: Bazel Output Version run: bazelisk --version - name: Bazel Test - run: bazelisk test ... --deleted_packages=codelab/src/test/codelab --test_output=errors # Exclude codelab exercises as they are intentionally made to fail + # Exclude codelab exercises as they are intentionally made to fail + # Exclude conformance tests for time being until TextFormat.Parser fix is in upstream + run: bazelisk test ... --deleted_packages=//codelab/src/test/codelab,//conformance/src/test/java/dev/cel/conformance --test_output=errors - run: echo "🍏 This job's status is ${{ job.status }}." diff --git a/WORKSPACE b/WORKSPACE index 798ad38c8..04efe6010 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -149,10 +149,10 @@ http_archive( # cel-spec api/expr canonical protos http_archive( name = "cel_spec", - sha256 = "3ee09eb69dbe77722e9dee23dc48dc2cd9f765869fcf5ffb1226587c81791a0b", - strip_prefix = "cel-spec-0.15.0", + sha256 = "65a153c1c4d73a135c364a4955e6aabd1093f0ed291774d3637f350504505085", + strip_prefix = "cel-spec-0789389e13a0626ec3521e4f109acce360565ce6", urls = [ - "https://github.com/google/cel-spec/archive/refs/tags/v0.15.0.tar.gz", + "https://github.com/google/cel-spec/archive/0789389e13a0626ec3521e4f109acce360565ce6.tar.gz", ], ) diff --git a/checker/src/main/java/dev/cel/checker/CelProtoExprVisitor.java b/checker/src/main/java/dev/cel/checker/CelProtoExprVisitor.java index cd5656642..08552d56f 100644 --- a/checker/src/main/java/dev/cel/checker/CelProtoExprVisitor.java +++ b/checker/src/main/java/dev/cel/checker/CelProtoExprVisitor.java @@ -18,7 +18,7 @@ import dev.cel.common.CelProtoAbstractSyntaxTree; /** - * CEL expression visitor implementation based on the {@link com.google.api.expr.Expr} proto. + * CEL expression visitor implementation based on the {@link dev.cel.expr.Expr} proto. * *

Note: Prefer using {@link dev.cel.common.ast.CelExprVisitor} if protobuf support is not * needed. diff --git a/common/src/main/java/dev/cel/common/CelProtoAbstractSyntaxTree.java b/common/src/main/java/dev/cel/common/CelProtoAbstractSyntaxTree.java index ef69c174b..f8374e114 100644 --- a/common/src/main/java/dev/cel/common/CelProtoAbstractSyntaxTree.java +++ b/common/src/main/java/dev/cel/common/CelProtoAbstractSyntaxTree.java @@ -104,12 +104,12 @@ private CelProtoAbstractSyntaxTree(CelAbstractSyntaxTree ast) { this.checkedExpr = checkedExprBuilder.build(); } - /** Construct an abstract syntax tree from a {@link com.google.api.expr.CheckedExpr}. */ + /** Construct an abstract syntax tree from a {@link dev.cel.expr.CheckedExpr}. */ public static CelProtoAbstractSyntaxTree fromCheckedExpr(CheckedExpr checkedExpr) { return new CelProtoAbstractSyntaxTree(checkedExpr); } - /** Construct an abstract syntax tree from a {@link com.google.api.expr.ParsedExpr}. */ + /** Construct an abstract syntax tree from a {@link dev.cel.expr.ParsedExpr}. */ public static CelProtoAbstractSyntaxTree fromParsedExpr(ParsedExpr parsedExpr) { return new CelProtoAbstractSyntaxTree( CheckedExpr.newBuilder() @@ -137,7 +137,7 @@ public CelAbstractSyntaxTree getAst() { } /** - * Returns the underlying {@link com.google.api.expr.Expr} representation of the abstract syntax + * Returns the underlying {@link dev.cel.expr.Expr} representation of the abstract syntax * tree. */ @CheckReturnValue @@ -146,7 +146,7 @@ public Expr getExpr() { } /** - * Returns the underlying {@link com.google.api.expr.CheckedExpr} representation of the abstract + * Returns the underlying {@link dev.cel.expr.CheckedExpr} representation of the abstract * syntax tree. Throws {@link java.lang.IllegalStateException} if {@link * CelAbstractSyntaxTree#isChecked} is false. */ @@ -159,7 +159,7 @@ public CheckedExpr toCheckedExpr() { } /** - * Returns the underlying {@link com.google.api.expr.SourceInfo} representation of the abstract + * Returns the underlying {@link dev.cel.expr.SourceInfo} representation of the abstract * syntax tree. */ @CheckReturnValue @@ -168,7 +168,7 @@ public SourceInfo getSourceInfo() { } /** - * Returns the underlying {@link com.google.api.expr.ParsedExpr} representation of the abstract + * Returns the underlying {@link dev.cel.expr.ParsedExpr} representation of the abstract * syntax tree. */ @CheckReturnValue diff --git a/common/src/main/java/dev/cel/common/internal/Constants.java b/common/src/main/java/dev/cel/common/internal/Constants.java index 0367d879a..528099840 100644 --- a/common/src/main/java/dev/cel/common/internal/Constants.java +++ b/common/src/main/java/dev/cel/common/internal/Constants.java @@ -26,7 +26,7 @@ import java.util.PrimitiveIterator; /** - * Internal utility class for working with {@link com.google.api.expr.Constant}. + * Internal utility class for working with {@link dev.cel.expr.Constant}. * *

CEL Library Internals. Do Not Use. */ diff --git a/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java b/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java index 6466ee9c9..1147da7ad 100644 --- a/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java +++ b/common/src/main/java/dev/cel/common/internal/DefaultInstanceMessageFactory.java @@ -38,7 +38,7 @@ *

CEL Library Internals. Do Not Use. */ @Internal -final class DefaultInstanceMessageFactory { +public final class DefaultInstanceMessageFactory { // Controls how many times we should recursively inspect a nested message for building fully // qualified java class name before aborting. @@ -87,7 +87,7 @@ public Optional getPrototype(Descriptor descriptor) { * Retrieves the full Java class name from the given descriptor * * @return fully qualified class name. - *

Example 1: com.google.api.expr.Value + *

Example 1: dev.cel.expr.Value *

Example 2: com.google.rpc.context.AttributeContext$Resource (Nested classes) *

Example 3: com.google.api.expr.cel.internal.testdata$SingleFileProto$SingleFile$Path * (Nested class with java multiple files disabled) diff --git a/conformance/src/test/java/dev/cel/conformance/BUILD.bazel b/conformance/src/test/java/dev/cel/conformance/BUILD.bazel new file mode 100644 index 000000000..5f1380277 --- /dev/null +++ b/conformance/src/test/java/dev/cel/conformance/BUILD.bazel @@ -0,0 +1,152 @@ +load("//conformance/src/test/java/dev/cel/conformance:conformance_test.bzl", "conformance_test") + +package(default_applicable_licenses = [ + "//:license", +]) + +exports_files([ + "conformance_test.bzl", + "conformance_test.sh", +]) + +java_library( + name = "run", + testonly = True, + srcs = glob(["*.java"]), + deps = [ + "//:java_truth", + "//checker:checker_builder", + "//common", + "//common:compiler_common", + "//common:options", + "//common/internal:default_instance_message_factory", + "//common/types", + "//common/types:type_providers", + "//compiler", + "//extensions", + "//extensions:optional_library", + "//parser", + "//parser:macro", + "//parser:parser_builder", + "//runtime", + "@@protobuf~//java/core", + "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1:simple_java_proto", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", + "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", + "@maven//:com_google_guava_guava", + "@maven//:com_google_truth_extensions_truth_proto_extension", + "@maven//:junit_junit", + ], +) + +_ALL_TESTS = [ + "@cel_spec//tests/simple:testdata/basic.textproto", + "@cel_spec//tests/simple:testdata/bindings_ext.textproto", + "@cel_spec//tests/simple:testdata/comparisons.textproto", + "@cel_spec//tests/simple:testdata/conversions.textproto", + "@cel_spec//tests/simple:testdata/dynamic.textproto", + "@cel_spec//tests/simple:testdata/encoders_ext.textproto", + "@cel_spec//tests/simple:testdata/enums.textproto", + "@cel_spec//tests/simple:testdata/fields.textproto", + "@cel_spec//tests/simple:testdata/fp_math.textproto", + "@cel_spec//tests/simple:testdata/integer_math.textproto", + "@cel_spec//tests/simple:testdata/lists.textproto", + "@cel_spec//tests/simple:testdata/logic.textproto", + "@cel_spec//tests/simple:testdata/macros.textproto", + "@cel_spec//tests/simple:testdata/math_ext.textproto", + "@cel_spec//tests/simple:testdata/namespace.textproto", + "@cel_spec//tests/simple:testdata/optionals.textproto", + "@cel_spec//tests/simple:testdata/parse.textproto", + "@cel_spec//tests/simple:testdata/plumbing.textproto", + "@cel_spec//tests/simple:testdata/proto2.textproto", + "@cel_spec//tests/simple:testdata/proto3.textproto", + "@cel_spec//tests/simple:testdata/proto2_ext.textproto", + "@cel_spec//tests/simple:testdata/string.textproto", + "@cel_spec//tests/simple:testdata/string_ext.textproto", + "@cel_spec//tests/simple:testdata/timestamps.textproto", + "@cel_spec//tests/simple:testdata/unknowns.textproto", + "@cel_spec//tests/simple:testdata/wrappers.textproto", +] + +_TESTS_TO_SKIP = [ + # Tests which require spec changes. + # TODO: Deprecate Duration.get_milliseconds + "timestamps/duration_converters/get_milliseconds", + + # Broken test cases which should be supported. + # TODO: Invalid bytes to string conversion should error. + "conversions/string/bytes_invalid", + # TODO: Support setting / getting enum values out of the defined enum value range. + "enums/legacy_proto2/select_big,select_neg", + "enums/legacy_proto2/assign_standalone_int_big,assign_standalone_int_neg", + # TODO: Generate errors on enum value assignment overflows for proto3. + "enums/legacy_proto3/assign_standalone_int_too_big,assign_standalone_int_too_neg", + # TODO: Ensure overflow occurs on conversions of double values which might not work properly on all platforms. + "conversions/int/double_int_min_range", + # TODO: Duration and timestamp operations should error on overflow. + "timestamps/duration_range/from_string_under,from_string_over", + "timestamps/timestamp_range/sub_time_duration_over,sub_time_duration_under", + # TODO: Ensure adding negative duration values is appropriately supported. + "timestamps/timestamp_arithmetic/add_time_to_duration_nanos_negative", + + # Skip until fixed. + "wrappers/field_mask/to_json", + "wrappers/empty/to_json", + "wrappers/duration/to_json", + "wrappers/timestamp/to_json", + "fields/qualified_identifier_resolution/map_value_repeat_key_heterogeneous", + # TODO: Add strings.quote. + "string_ext/quote", + + # TODO: Fix null assignment to a field + "proto2/set_null/single_message", + "proto2/set_null/single_duration", + "proto2/set_null/single_timestamp", + "proto3/set_null/single_message", + "proto3/set_null/single_duration", + "proto3/set_null/single_timestamp", + + # Future features for CEL 1.0 + # TODO: Strong typing support for enums, specified but not implemented. + "enums/strong_proto2", + "enums/strong_proto3", + + # com.google.protobuf.TextFormat does not conform to the spec. Unknown enum values are supposed + # to be allowed in proto3. Currently they are rejected. + # "enums/legacy_proto3/select_big", + # "enums/legacy_proto3/select_neg", + # "enums/legacy_proto3/assign_standalone_int_big", + # "enums/legacy_proto3/assign_standalone_int_neg", + + # Not yet implemented. + "math_ext/ceil", + "math_ext/floor", + "math_ext/round", + "math_ext/trunc", + "math_ext/abs", + "math_ext/sign", + "math_ext/isNaN", + "math_ext/isInf", + "math_ext/isFinite", + "math_ext/bit_and", + "math_ext/bit_or", + "math_ext/bit_xor", + "math_ext/bit_not", + "math_ext/bit_shift_left", + "math_ext/bit_shift_right", +] + +conformance_test( + name = "conformance", + dashboard = False, + data = _ALL_TESTS, + skip_tests = _TESTS_TO_SKIP, +) + +conformance_test( + name = "conformance_dashboard", + dashboard = True, + data = _ALL_TESTS, +) diff --git a/conformance/src/test/java/dev/cel/conformance/ConformanceTest.java b/conformance/src/test/java/dev/cel/conformance/ConformanceTest.java new file mode 100644 index 000000000..32c10bf4d --- /dev/null +++ b/conformance/src/test/java/dev/cel/conformance/ConformanceTest.java @@ -0,0 +1,408 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.conformance; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; + +import dev.cel.expr.Decl; +import com.google.api.expr.test.v1.SimpleProto.SimpleTest; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.v1alpha1.ExprValue; +import com.google.api.expr.v1alpha1.ListValue; +import com.google.api.expr.v1alpha1.MapValue; +import com.google.api.expr.v1alpha1.Value; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.primitives.UnsignedLong; +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.Message; +import com.google.protobuf.NullValue; +import com.google.protobuf.TypeRegistry; +import dev.cel.checker.CelChecker; +import dev.cel.common.CelDescriptorUtil; +import dev.cel.common.CelDescriptors; +import dev.cel.common.CelOptions; +import dev.cel.common.CelValidationResult; +import dev.cel.common.internal.DefaultInstanceMessageFactory; +import dev.cel.common.types.CelType; +import dev.cel.common.types.ListType; +import dev.cel.common.types.MapType; +import dev.cel.common.types.SimpleType; +import dev.cel.compiler.CelCompilerFactory; +import dev.cel.extensions.CelExtensions; +import dev.cel.extensions.CelOptionalLibrary; +import dev.cel.parser.CelParser; +import dev.cel.parser.CelParserFactory; +import dev.cel.parser.CelStandardMacro; +import dev.cel.runtime.CelEvaluationException; +import dev.cel.runtime.CelRuntime; +import dev.cel.runtime.CelRuntime.Program; +import dev.cel.runtime.CelRuntimeFactory; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import org.junit.runners.model.Statement; + +// Qualifying proto2/proto3 TestAllTypes makes it less clear. +@SuppressWarnings("UnnecessarilyFullyQualified") +public final class ConformanceTest extends Statement { + + static final TypeRegistry DEFAULT_TYPE_REGISTRY = newDefaultTypeRegistry(); + static final ExtensionRegistry DEFAULT_EXTENSION_REGISTRY = newDefaultExtensionRegistry(); + + private static ExtensionRegistry newDefaultExtensionRegistry() { + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + com.google.api.expr.test.v1.proto2.TestAllTypesExtensions.registerAllExtensions( + extensionRegistry); + + return extensionRegistry; + } + + private static TypeRegistry newDefaultTypeRegistry() { + CelDescriptors allDescriptors = + CelDescriptorUtil.getAllDescriptorsFromFileDescriptor( + ImmutableList.of( + com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.getDescriptor() + .getFile(), + com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.getDescriptor() + .getFile(), + com.google.api.expr.test.v1.proto2.TestAllTypesExtensions.getDescriptor() + .getFile())); + + return TypeRegistry.newBuilder().add(allDescriptors.messageTypeDescriptors()).build(); + } + + private static final CelOptions OPTIONS = + CelOptions.current() + .enableTimestampEpoch(true) + .enableUnsignedLongs(true) + .enableHeterogeneousNumericComparisons(true) + .enableProtoDifferencerEquality(true) + .enableOptionalSyntax(true) + .build(); + + private static final CelParser PARSER_WITH_MACROS = + CelParserFactory.standardCelParserBuilder() + .setOptions(OPTIONS) + .addLibraries( + CelExtensions.bindings(), + CelExtensions.encoders(), + CelExtensions.math(OPTIONS), + CelExtensions.protos(), + CelExtensions.sets(), + CelExtensions.strings(), + CelOptionalLibrary.INSTANCE) + .setStandardMacros(CelStandardMacro.STANDARD_MACROS) + .build(); + + private static final CelParser PARSER_WITHOUT_MACROS = + CelParserFactory.standardCelParserBuilder() + .setOptions(OPTIONS) + .addLibraries( + CelExtensions.bindings(), + CelExtensions.encoders(), + CelExtensions.math(OPTIONS), + CelExtensions.protos(), + CelExtensions.sets(), + CelExtensions.strings(), + CelOptionalLibrary.INSTANCE) + .setStandardMacros() + .build(); + + private static CelParser getParser(SimpleTest test) { + return test.getDisableMacros() ? PARSER_WITHOUT_MACROS : PARSER_WITH_MACROS; + } + + private static CelChecker getChecker(SimpleTest test) throws Exception { + ImmutableList.Builder decls = + ImmutableList.builderWithExpectedSize(test.getTypeEnvCount()); + for (com.google.api.expr.v1alpha1.Decl decl : test.getTypeEnvList()) { + decls.add(Decl.parseFrom(decl.toByteArray(), DEFAULT_EXTENSION_REGISTRY)); + } + return CelCompilerFactory.standardCelCheckerBuilder() + .setOptions(OPTIONS) + .setContainer(test.getContainer()) + .addDeclarations(decls.build()) + .addFileTypes(TestAllTypesExtensions.getDescriptor()) + .addLibraries( + CelExtensions.bindings(), + CelExtensions.encoders(), + CelExtensions.math(OPTIONS), + CelExtensions.sets(), + CelExtensions.strings(), + CelOptionalLibrary.INSTANCE) + .addMessageTypes( + com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.getDescriptor()) + .addMessageTypes( + com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.getDescriptor()) + .build(); + } + + private static final CelRuntime RUNTIME = + CelRuntimeFactory.standardCelRuntimeBuilder() + .setOptions(OPTIONS) + .addLibraries( + CelExtensions.encoders(), + CelExtensions.math(OPTIONS), + CelExtensions.sets(), + CelExtensions.strings(), + CelOptionalLibrary.INSTANCE) + .addMessageTypes( + com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.getDescriptor()) + .addMessageTypes( + com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.getDescriptor()) + .build(); + + private static ImmutableMap getBindings(SimpleTest test) throws Exception { + ImmutableMap.Builder bindings = + ImmutableMap.builderWithExpectedSize(test.getBindingsCount()); + for (Map.Entry entry : test.getBindingsMap().entrySet()) { + bindings.put(entry.getKey(), fromExprValue(entry.getValue())); + } + return bindings.buildOrThrow(); + } + + private static Object fromExprValue(ExprValue value) throws Exception { + switch (value.getKindCase()) { + case VALUE: + return fromValue(value.getValue()); + default: + throw new IllegalArgumentException( + String.format("Unexpected binding value kind: %s", value.getKindCase())); + } + } + + private static Object fromValue(Value value) throws Exception { + switch (value.getKindCase()) { + case NULL_VALUE: + return value.getNullValue(); + case BOOL_VALUE: + return value.getBoolValue(); + case INT64_VALUE: + return value.getInt64Value(); + case UINT64_VALUE: + return UnsignedLong.fromLongBits(value.getUint64Value()); + case DOUBLE_VALUE: + return value.getDoubleValue(); + case STRING_VALUE: + return value.getStringValue(); + case BYTES_VALUE: + return value.getBytesValue(); + case ENUM_VALUE: + return value.getEnumValue(); + case OBJECT_VALUE: + { + Any object = value.getObjectValue(); + Descriptor descriptor = + DEFAULT_TYPE_REGISTRY.getDescriptorForTypeUrl(object.getTypeUrl()); + Message prototype = + DefaultInstanceMessageFactory.getInstance() + .getPrototype(descriptor) + .orElseThrow( + () -> + new NoSuchElementException( + "Could not find a default message for: " + descriptor.getFullName())); + return prototype + .getParserForType() + .parseFrom(object.getValue(), DEFAULT_EXTENSION_REGISTRY); + } + case MAP_VALUE: + { + MapValue map = value.getMapValue(); + ImmutableMap.Builder builder = + ImmutableMap.builderWithExpectedSize(map.getEntriesCount()); + for (MapValue.Entry entry : map.getEntriesList()) { + builder.put(fromValue(entry.getKey()), fromValue(entry.getValue())); + } + return builder.buildOrThrow(); + } + case LIST_VALUE: + { + ListValue list = value.getListValue(); + ImmutableList.Builder builder = + ImmutableList.builderWithExpectedSize(list.getValuesCount()); + for (Value element : list.getValuesList()) { + builder.add(fromValue(element)); + } + return builder.build(); + } + case TYPE_VALUE: + return value.getTypeValue(); + default: + throw new IllegalArgumentException( + String.format("Unexpected binding value kind: %s", value.getKindCase())); + } + } + + private static ExprValue toExprValue(Object object, CelType type) throws Exception { + if (object instanceof ExprValue) { + return (ExprValue) object; + } + return ExprValue.newBuilder().setValue(toValue(object, type)).build(); + } + + @SuppressWarnings("unchecked") + private static Value toValue(Object object, CelType type) throws Exception { + if (object == null) { + object = NullValue.NULL_VALUE; + } + if (object instanceof dev.cel.expr.Value) { + object = + Value.parseFrom( + ((dev.cel.expr.Value) object).toByteArray(), DEFAULT_EXTENSION_REGISTRY); + } + if (object instanceof Value) { + return (Value) object; + } + if (object instanceof NullValue) { + return Value.newBuilder().setNullValue((NullValue) object).build(); + } + if (object instanceof Boolean) { + return Value.newBuilder().setBoolValue((Boolean) object).build(); + } + if (object instanceof UnsignedLong) { + switch (type.kind()) { + case UINT: + case DYN: + case ANY: + return Value.newBuilder().setUint64Value(((UnsignedLong) object).longValue()).build(); + default: + throw new IllegalArgumentException(String.format("Unexpected result type: %s", type)); + } + } + if (object instanceof Long) { + switch (type.kind()) { + case INT: + case DYN: + case ANY: + return Value.newBuilder().setInt64Value((Long) object).build(); + case UINT: + return Value.newBuilder().setUint64Value((Long) object).build(); + default: + throw new IllegalArgumentException(String.format("Unexpected result type: %s", type)); + } + } + if (object instanceof Double) { + return Value.newBuilder().setDoubleValue((Double) object).build(); + } + if (object instanceof String) { + switch (type.kind()) { + case TYPE: + return Value.newBuilder().setTypeValue((String) object).build(); + case STRING: + case DYN: + case ANY: + return Value.newBuilder().setStringValue((String) object).build(); + default: + throw new IllegalArgumentException(String.format("Unexpected result type: %s", type)); + } + } + if (object instanceof ByteString) { + return Value.newBuilder().setBytesValue((ByteString) object).build(); + } + if (object instanceof List) { + CelType elemType = type instanceof ListType ? ((ListType) type).elemType() : SimpleType.DYN; + ListValue.Builder builder = ListValue.newBuilder(); + for (Object element : ((List) object)) { + builder.addValues(toValue(element, elemType)); + } + return Value.newBuilder().setListValue(builder.build()).build(); + } + if (object instanceof Map) { + CelType keyType = type instanceof MapType ? ((MapType) type).keyType() : SimpleType.DYN; + CelType valueType = type instanceof MapType ? ((MapType) type).valueType() : SimpleType.DYN; + MapValue.Builder builder = MapValue.newBuilder(); + for (Map.Entry entry : ((Map) object).entrySet()) { + builder.addEntries( + MapValue.Entry.newBuilder() + .setKey(toValue(entry.getKey(), keyType)) + .setValue(toValue(entry.getValue(), valueType)) + .build()); + } + return Value.newBuilder().setMapValue(builder.build()).build(); + } + if (object instanceof Message) { + return Value.newBuilder().setObjectValue(Any.pack((Message) object)).build(); + } + throw new IllegalArgumentException( + String.format("Unexpected result type: %s", object.getClass())); + } + + private static SimpleTest defaultTestMatcherToTrueIfUnset(SimpleTest test) { + if (test.getResultMatcherCase() == SimpleTest.ResultMatcherCase.RESULTMATCHER_NOT_SET) { + return test.toBuilder().setValue(Value.newBuilder().setBoolValue(true).build()).build(); + } + return test; + } + + private final String name; + private final SimpleTest test; + private final boolean skip; + + public ConformanceTest(String name, SimpleTest test, boolean skip) { + this.name = Preconditions.checkNotNull(name); + this.test = + Preconditions.checkNotNull( + defaultTestMatcherToTrueIfUnset(Preconditions.checkNotNull(test))); + this.skip = skip; + } + + public String getName() { + return name; + } + + public boolean shouldSkip() { + return skip; + } + + @Override + public void evaluate() throws Throwable { + CelValidationResult response = getParser(test).parse(test.getExpr(), test.getName()); + assertThat(response.hasError()).isFalse(); + response = getChecker(test).check(response.getAst()); + assertThat(response.hasError()).isFalse(); + Program program = RUNTIME.createProgram(response.getAst()); + ExprValue result = null; + CelEvaluationException error = null; + try { + result = toExprValue(program.eval(getBindings(test)), response.getAst().getResultType()); + } catch (CelEvaluationException e) { + error = e; + } + switch (test.getResultMatcherCase()) { + case VALUE: + assertThat(error).isNull(); + assertThat(result).isNotNull(); + assertThat(result) + .ignoringRepeatedFieldOrderOfFieldDescriptors( + MapValue.getDescriptor().findFieldByName("entries")) + .unpackingAnyUsing(DEFAULT_TYPE_REGISTRY, DEFAULT_EXTENSION_REGISTRY) + .isEqualTo(ExprValue.newBuilder().setValue(test.getValue()).build()); + break; + case EVAL_ERROR: + assertThat(result).isNull(); + assertThat(error).isNotNull(); + break; + default: + throw new IllegalStateException( + String.format("Unexpected matcher kind: %s", test.getResultMatcherCase())); + } + } +} diff --git a/conformance/src/test/java/dev/cel/conformance/ConformanceTestRunner.java b/conformance/src/test/java/dev/cel/conformance/ConformanceTestRunner.java new file mode 100644 index 000000000..a9f41c87f --- /dev/null +++ b/conformance/src/test/java/dev/cel/conformance/ConformanceTestRunner.java @@ -0,0 +1,128 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.conformance; + +import static dev.cel.conformance.ConformanceTest.DEFAULT_EXTENSION_REGISTRY; +import static dev.cel.conformance.ConformanceTest.DEFAULT_TYPE_REGISTRY; + +import com.google.api.expr.test.v1.SimpleProto.SimpleTest; +import com.google.api.expr.test.v1.SimpleProto.SimpleTestFile; +import com.google.api.expr.test.v1.SimpleProto.SimpleTestSection; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedMap; +import com.google.protobuf.TextFormat; +import java.io.BufferedReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import org.junit.runner.Description; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.ParentRunner; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.TestClass; + +public final class ConformanceTestRunner extends ParentRunner { + + private static final Splitter SPLITTER = Splitter.on(",").omitEmptyStrings(); + + private final ImmutableSortedMap testFiles; + private final ImmutableList testsToSkip; + + private static ImmutableSortedMap loadTestFiles() { + List testPaths = + SPLITTER.splitToList(System.getProperty("dev.cel.conformance.ConformanceTests.tests")); + try { + TextFormat.Parser parser = + TextFormat.Parser.newBuilder().setTypeRegistry(DEFAULT_TYPE_REGISTRY).build(); + ImmutableSortedMap.Builder testFiles = + ImmutableSortedMap.naturalOrder(); + for (String testPath : testPaths) { + SimpleTestFile.Builder fileBuilder = SimpleTestFile.newBuilder(); + try (BufferedReader input = + Files.newBufferedReader(Paths.get(testPath), StandardCharsets.UTF_8)) { + parser.merge(input, DEFAULT_EXTENSION_REGISTRY, fileBuilder); + } + SimpleTestFile testFile = fileBuilder.build(); + testFiles.put(testFile.getName(), testFile); + } + return testFiles.buildOrThrow(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public ConformanceTestRunner(Class clazz) throws InitializationError { + super(new TestClass(clazz)); + Preconditions.checkArgument(ConformanceTests.class.equals(clazz)); + testFiles = loadTestFiles(); + testsToSkip = + ImmutableList.copyOf( + SPLITTER.splitToList( + System.getProperty("dev.cel.conformance.ConformanceTests.skip_tests"))); + } + + private boolean shouldSkipTest(String name) { + for (String testToSkip : testsToSkip) { + if (name.startsWith(testToSkip)) { + String consumedName = name.substring(testToSkip.length()); + if (consumedName.isEmpty() || consumedName.startsWith("/")) { + return true; + } + } + } + return false; + } + + @Override + protected List getChildren() { + ArrayList tests = new ArrayList<>(); + for (SimpleTestFile testFile : testFiles.values()) { + for (SimpleTestSection testSection : testFile.getSectionList()) { + for (SimpleTest test : testSection.getTestList()) { + String name = + String.format("%s/%s/%s", testFile.getName(), testSection.getName(), test.getName()); + tests.add( + new ConformanceTest(name, test, test.getDisableCheck() || shouldSkipTest(name))); + } + } + } + return tests; + } + + @Override + protected Description describeChild(ConformanceTest child) { + return Description.createTestDescription( + ConformanceTest.class, child.getName(), ConformanceTest.class.getAnnotations()); + } + + @Override + protected void runChild(ConformanceTest child, RunNotifier notifier) { + Description desc = describeChild(child); + if (isIgnored(child)) { + notifier.fireTestIgnored(desc); + } else { + runLeaf(child, desc, notifier); + } + } + + @Override + protected boolean isIgnored(ConformanceTest child) { + return child.shouldSkip(); + } +} diff --git a/conformance/src/test/java/dev/cel/conformance/ConformanceTests.java b/conformance/src/test/java/dev/cel/conformance/ConformanceTests.java new file mode 100644 index 000000000..58de114ba --- /dev/null +++ b/conformance/src/test/java/dev/cel/conformance/ConformanceTests.java @@ -0,0 +1,20 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.conformance; + +import org.junit.runner.RunWith; + +@RunWith(ConformanceTestRunner.class) +public class ConformanceTests {} diff --git a/conformance/src/test/java/dev/cel/conformance/conformance_test.bzl b/conformance/src/test/java/dev/cel/conformance/conformance_test.bzl new file mode 100644 index 000000000..8201f4ce3 --- /dev/null +++ b/conformance/src/test/java/dev/cel/conformance/conformance_test.bzl @@ -0,0 +1,80 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +""" +This module contains build rules for generating the conformance test targets. +""" + +load("@rules_java//java:defs.bzl", "java_test") + +# Converts the list of tests to skip from the format used by the original Go test runner to a single +# flag value where each test is separated by a comma. It also performs expansion, for example +# `foo/bar,baz` becomes two entries which are `foo/bar` and `foo/baz`. +def _expand_tests_to_skip(tests_to_skip): + result = [] + for test_to_skip in tests_to_skip: + comma = test_to_skip.find(",") + if comma == -1: + result.append(test_to_skip) + continue + slash = test_to_skip.rfind("/", 0, comma) + if slash == -1: + slash = 0 + else: + slash = slash + 1 + for part in test_to_skip[slash:].split(","): + result.append(test_to_skip[0:slash] + part) + return result + +def _conformance_test_args(data, skip_tests): + args = [] + args.append("-Ddev.cel.conformance.ConformanceTests.skip_tests={}".format(",".join(_expand_tests_to_skip(skip_tests)))) + args.append("-Ddev.cel.conformance.ConformanceTests.tests={}".format(",".join(["$(location " + test + ")" for test in data]))) + return args + +def conformance_test(name, data, dashboard, skip_tests = []): + if dashboard: + java_test( + name = "_" + name, + jvm_flags = _conformance_test_args(data, skip_tests), + data = data, + size = "small", + test_class = "dev.cel.conformance.ConformanceTests", + runtime_deps = ["//conformance/src/test/java/dev/cel/conformance:run"], + tags = [ + "manual", + "notap", + ], + ) + native.sh_test( + name = name, + size = "small", + srcs = ["//conformance/src/test/java/dev/cel/conformance:conformance_test.sh"], + args = ["$(location :_" + name + ")"], + data = [":_" + name], + tags = [ + "guitar", + "manual", + "notap", + ], + ) + else: + java_test( + name = name, + jvm_flags = _conformance_test_args(data, skip_tests), + data = data, + size = "small", + test_class = "dev.cel.conformance.ConformanceTests", + runtime_deps = ["//conformance/src/test/java/dev/cel/conformance:run"], + ) diff --git a/conformance/src/test/java/dev/cel/conformance/conformance_test.sh b/conformance/src/test/java/dev/cel/conformance/conformance_test.sh new file mode 100755 index 000000000..c00f21c7a --- /dev/null +++ b/conformance/src/test/java/dev/cel/conformance/conformance_test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +(exec "$@") +rc = $? +if [ $rc -eq 1 ]; then + rc = 0 +fi +exit $rc diff --git a/testing/src/main/java/dev/cel/testing/CelDebug.java b/testing/src/main/java/dev/cel/testing/CelDebug.java index 58bb2a6b2..f28383614 100644 --- a/testing/src/main/java/dev/cel/testing/CelDebug.java +++ b/testing/src/main/java/dev/cel/testing/CelDebug.java @@ -42,12 +42,12 @@ public String adorn(EntryOrBuilder entry) { } }; - /** Returns the unadorned string representation of {@link com.google.api.expr.ExprOrBuilder}. */ + /** Returns the unadorned string representation of {@link dev.cel.expr.ExprOrBuilder}. */ public static String toDebugString(ExprOrBuilder expr) { return toAdornedDebugString(expr, UNADORNER); } - /** Returns the adorned string representation of {@link com.google.api.expr.ExprOrBuilder}. */ + /** Returns the adorned string representation of {@link dev.cel.expr.ExprOrBuilder}. */ public static String toAdornedDebugString(ExprOrBuilder expr, CelAdorner adorner) { CelDebug debug = new CelDebug(checkNotNull(adorner)); debug.appendExpr(checkNotNull(expr)); From 53a33aa97c4e64b5ddf66d242b80576de822488a Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Tue, 13 Aug 2024 09:20:21 -0700 Subject: [PATCH 12/33] Fix runtime equality behavior for sets extension PiperOrigin-RevId: 662542663 --- .../main/java/dev/cel/extensions/BUILD.bazel | 5 +- .../dev/cel/extensions/CelExtensions.java | 23 +- .../dev/cel/extensions/CelSetsExtensions.java | 121 +++++------ .../cel/extensions/CelSetsExtensionsTest.java | 205 +++++++++++++++++- 4 files changed, 268 insertions(+), 86 deletions(-) diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel index a6e35911d..b92bd9b54 100644 --- a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel @@ -137,10 +137,13 @@ java_library( deps = [ "//checker:checker_builder", "//common:compiler_common", - "//common/internal:comparison_functions", + "//common:options", + "//common/internal:default_message_factory", + "//common/internal:dynamic_proto", "//common/types", "//compiler:compiler_builder", "//runtime", + "//runtime:runtime_helper", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], diff --git a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java index 662246283..353acdad3 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java @@ -34,7 +34,6 @@ public final class CelExtensions { private static final CelProtoExtensions PROTO_EXTENSIONS = new CelProtoExtensions(); private static final CelBindingsExtensions BINDINGS_EXTENSIONS = new CelBindingsExtensions(); private static final CelEncoderExtensions ENCODER_EXTENSIONS = new CelEncoderExtensions(); - private static final CelSetsExtensions SET_EXTENSIONS = new CelSetsExtensions(); /** * Extended functions for string manipulation. @@ -175,6 +174,14 @@ public static CelEncoderExtensions encoders() { return ENCODER_EXTENSIONS; } + /** + * @deprecated Use {@link #sets(CelOptions)} instead. + */ + @Deprecated + public static CelSetsExtensions sets() { + return sets(CelOptions.DEFAULT); + } + /** * Extended functions for Set manipulation. * @@ -184,8 +191,8 @@ public static CelEncoderExtensions encoders() { * future additions. To expose only a subset of functions, use {@link * #sets(CelSetExtensions.Function...)} instead. */ - public static CelSetsExtensions sets() { - return SET_EXTENSIONS; + public static CelSetsExtensions sets(CelOptions celOptions) { + return new CelSetsExtensions(celOptions); } /** @@ -195,8 +202,9 @@ public static CelSetsExtensions sets() { * *

This will include only the specific functions denoted by {@link CelSetsExtensions.Function}. */ - public static CelSetsExtensions sets(CelSetsExtensions.Function... functions) { - return sets(ImmutableSet.copyOf(functions)); + public static CelSetsExtensions sets( + CelOptions celOptions, CelSetsExtensions.Function... functions) { + return sets(celOptions, ImmutableSet.copyOf(functions)); } /** @@ -206,8 +214,9 @@ public static CelSetsExtensions sets(CelSetsExtensions.Function... functions) { * *

This will include only the specific functions denoted by {@link CelSetsExtensions.Function}. */ - public static CelSetsExtensions sets(Set functions) { - return new CelSetsExtensions(functions); + public static CelSetsExtensions sets( + CelOptions celOptions, Set functions) { + return new CelSetsExtensions(celOptions, functions); } /** diff --git a/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java index e410edade..1a3cb196a 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelSetsExtensions.java @@ -18,8 +18,10 @@ import com.google.errorprone.annotations.Immutable; import dev.cel.checker.CelCheckerBuilder; import dev.cel.common.CelFunctionDecl; +import dev.cel.common.CelOptions; import dev.cel.common.CelOverloadDecl; -import dev.cel.common.internal.ComparisonFunctions; +import dev.cel.common.internal.DefaultMessageFactory; +import dev.cel.common.internal.DynamicProto; import dev.cel.common.types.ListType; import dev.cel.common.types.SimpleType; import dev.cel.common.types.TypeParamType; @@ -27,9 +29,9 @@ import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntimeBuilder; import dev.cel.runtime.CelRuntimeLibrary; +import dev.cel.runtime.RuntimeEquality; import java.util.Collection; import java.util.Iterator; -import java.util.List; import java.util.Set; /** @@ -64,6 +66,9 @@ public final class CelSetsExtensions implements CelCompilerLibrary, CelRuntimeLi + " are unique, so size does not factor into the computation. If either list is empty," + " the result will be false."; + private static final RuntimeEquality RUNTIME_EQUALITY = + new RuntimeEquality(DynamicProto.create(DefaultMessageFactory.INSTANCE)); + /** Denotes the set extension function. */ public enum Function { CONTAINS( @@ -74,12 +79,7 @@ public enum Function { SET_CONTAINS_OVERLOAD_DOC, SimpleType.BOOL, ListType.create(TypeParamType.create("T")), - ListType.create(TypeParamType.create("T")))), - CelRuntime.CelFunctionBinding.from( - "list_sets_contains_list", - Collection.class, - Collection.class, - CelSetsExtensions::containsAll)), + ListType.create(TypeParamType.create("T"))))), EQUIVALENT( CelFunctionDecl.newFunctionDeclaration( SET_EQUIVALENT_FUNCTION, @@ -88,12 +88,7 @@ public enum Function { SET_EQUIVALENT_OVERLOAD_DOC, SimpleType.BOOL, ListType.create(TypeParamType.create("T")), - ListType.create(TypeParamType.create("T")))), - CelRuntime.CelFunctionBinding.from( - "list_sets_equivalent_list", - Collection.class, - Collection.class, - (listA, listB) -> containsAll(listA, listB) && containsAll(listB, listA))), + ListType.create(TypeParamType.create("T"))))), INTERSECTS( CelFunctionDecl.newFunctionDeclaration( SET_INTERSECTS_FUNCTION, @@ -102,34 +97,29 @@ public enum Function { SET_INTERSECTS_OVERLOAD_DOC, SimpleType.BOOL, ListType.create(TypeParamType.create("T")), - ListType.create(TypeParamType.create("T")))), - CelRuntime.CelFunctionBinding.from( - "list_sets_intersects_list", - Collection.class, - Collection.class, - CelSetsExtensions::setIntersects)); + ListType.create(TypeParamType.create("T"))))); private final CelFunctionDecl functionDecl; - private final ImmutableSet functionBindings; String getFunction() { return functionDecl.name(); } - Function(CelFunctionDecl functionDecl, CelRuntime.CelFunctionBinding... functionBindings) { + Function(CelFunctionDecl functionDecl) { this.functionDecl = functionDecl; - this.functionBindings = ImmutableSet.copyOf(functionBindings); } } private final ImmutableSet functions; + private final CelOptions celOptions; - CelSetsExtensions() { - this(ImmutableSet.copyOf(Function.values())); + CelSetsExtensions(CelOptions celOptions) { + this(celOptions, ImmutableSet.copyOf(Function.values())); } - CelSetsExtensions(Set functions) { + CelSetsExtensions(CelOptions celOptions, Set functions) { this.functions = ImmutableSet.copyOf(functions); + this.celOptions = celOptions; } @Override @@ -139,7 +129,34 @@ public void setCheckerOptions(CelCheckerBuilder checkerBuilder) { @Override public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) { - functions.forEach(function -> runtimeBuilder.addFunctionBindings(function.functionBindings)); + for (Function function : functions) { + switch (function) { + case CONTAINS: + runtimeBuilder.addFunctionBindings( + CelRuntime.CelFunctionBinding.from( + "list_sets_contains_list", + Collection.class, + Collection.class, + this::containsAll)); + break; + case EQUIVALENT: + runtimeBuilder.addFunctionBindings( + CelRuntime.CelFunctionBinding.from( + "list_sets_equivalent_list", + Collection.class, + Collection.class, + (listA, listB) -> containsAll(listA, listB) && containsAll(listB, listA))); + break; + case INTERSECTS: + runtimeBuilder.addFunctionBindings( + CelRuntime.CelFunctionBinding.from( + "list_sets_intersects_list", + Collection.class, + Collection.class, + this::setIntersects)); + break; + } + } } /** @@ -150,9 +167,9 @@ public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) { *

This is picked verbatim as implemented in the Java standard library * Collections.containsAll() method. * - * @see #contains(Object) + * @see #contains(Object, Collection) */ - private static boolean containsAll(Collection list, Collection subList) { + private boolean containsAll(Collection list, Collection subList) { for (T e : subList) { if (!contains(e, list)) { return false; @@ -171,7 +188,7 @@ private static boolean containsAll(Collection list, Collection subList *

Source: * https://hg.openjdk.org/jdk8u/jdk8u-dev/jdk/file/c5d02f908fb2/src/share/classes/java/util/AbstractCollection.java#l98 */ - private static boolean contains(Object o, Collection list) { + private boolean contains(Object o, Collection list) { Iterator it = list.iterator(); if (o == null) { while (it.hasNext()) { @@ -182,7 +199,7 @@ private static boolean contains(Object o, Collection list) { } else { while (it.hasNext()) { Object item = it.next(); - if (objectsEquals(item, o)) { // TODO: Support Maps. + if (objectsEquals(item, o)) { return true; } } @@ -190,47 +207,11 @@ private static boolean contains(Object o, Collection list) { return false; } - private static boolean objectsEquals(Object o1, Object o2) { - if (o1 == o2) { - return true; - } - if (o1 == null || o2 == null) { - return false; - } - if (isNumeric(o1) && isNumeric(o2)) { - if (o1.getClass().equals(o2.getClass())) { - return o1.equals(o2); - } - return ComparisonFunctions.numericEquals((Number) o1, (Number) o2); - } - if (isList(o1) && isList(o2)) { - Collection list1 = (Collection) o1; - Collection list2 = (Collection) o2; - if (list1.size() != list2.size()) { - return false; - } - Iterator iterator1 = list1.iterator(); - Iterator iterator2 = list2.iterator(); - boolean result = true; - while (iterator1.hasNext() && iterator2.hasNext()) { - Object p1 = iterator1.next(); - Object p2 = iterator2.next(); - result = result && objectsEquals(p1, p2); - } - return result; - } - return o1.equals(o2); - } - - private static boolean isNumeric(Object o) { - return o instanceof Number; - } - - private static boolean isList(Object o) { - return o instanceof List; + private boolean objectsEquals(Object o1, Object o2) { + return RUNTIME_EQUALITY.objectEquals(o1, o2, celOptions); } - private static boolean setIntersects(Collection listA, Collection listB) { + private boolean setIntersects(Collection listA, Collection listB) { if (listA.isEmpty() || listB.isEmpty()) { return false; } diff --git a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java index 70396ee45..120ac25d6 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java @@ -22,6 +22,9 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.common.CelAbstractSyntaxTree; +import dev.cel.common.CelFunctionDecl; +import dev.cel.common.CelOptions; +import dev.cel.common.CelOverloadDecl; import dev.cel.common.CelValidationException; import dev.cel.common.CelValidationResult; import dev.cel.common.types.ListType; @@ -31,22 +34,44 @@ import dev.cel.extensions.CelSetsExtensions.Function; import dev.cel.runtime.CelEvaluationException; import dev.cel.runtime.CelRuntime; +import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.runtime.CelRuntimeFactory; +import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) public final class CelSetsExtensionsTest { + private static final CelOptions CEL_OPTIONS = + CelOptions.current().enableUnsignedLongs(true).build(); private static final CelCompiler COMPILER = CelCompilerFactory.standardCelCompilerBuilder() - .addLibraries(CelExtensions.sets()) + .addMessageTypes(TestAllTypes.getDescriptor()) + .setOptions(CEL_OPTIONS) + .setContainer("dev.cel.testing.testdata.proto3") + .addLibraries(CelExtensions.sets(CEL_OPTIONS)) .addVar("list", ListType.create(SimpleType.INT)) .addVar("subList", ListType.create(SimpleType.INT)) + .addFunctionDeclarations( + CelFunctionDecl.newFunctionDeclaration( + "new_int", + CelOverloadDecl.newGlobalOverload( + "new_int_int64", SimpleType.INT, SimpleType.INT))) .build(); private static final CelRuntime RUNTIME = - CelRuntimeFactory.standardCelRuntimeBuilder().addLibraries(CelExtensions.sets()).build(); + CelRuntimeFactory.standardCelRuntimeBuilder() + .addMessageTypes(TestAllTypes.getDescriptor()) + .addLibraries(CelExtensions.sets(CEL_OPTIONS)) + .setOptions(CEL_OPTIONS) + .addFunctionBindings( + CelFunctionBinding.from( + "new_int_int64", + Long.class, + // Intentionally return java.lang.Integer to test primitive type adaptation + Math::toIntExact)) + .build(); @Test public void contains_integerListWithSameValue_succeeds() throws Exception { @@ -70,6 +95,42 @@ public void contains_integerListAsExpression_succeeds() throws Exception { assertThat(result).isEqualTo(true); } + @Test + @TestParameters( + "{expression: 'sets.contains([TestAllTypes{}], [TestAllTypes{}])', expected: true}") + @TestParameters( + "{expression: 'sets.contains([TestAllTypes{single_int64: 1, single_uint64: 2u}]," + + " [TestAllTypes{single_int64: 1, single_uint64: 2u}])', expected: true}") + @TestParameters( + "{expression: 'sets.contains([TestAllTypes{single_any: [1.0, 2u, 3]}]," + + " [TestAllTypes{single_any: [1u, 2, 3.0]}])', expected: true}") + @TestParameters( + "{expression: 'sets.contains([TestAllTypes{single_int64: 1, single_uint64: 2u}]," + + " [TestAllTypes{single_int64: 2, single_uint64: 3u}])', expected: false}") + public void contains_withProtoMessage_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + + @Test + @TestParameters("{expression: 'sets.contains([new_int(1)], [1])', expected: true}") + @TestParameters("{expression: 'sets.contains([new_int(1)], [1.0, 1u])', expected: true}") + @TestParameters("{expression: 'sets.contains([new_int(2)], [1])', expected: false}") + public void contains_withFunctionReturningInteger_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + @Test @TestParameters("{list: [1, 2, 3, 4], subList: [1, 2, 3, 4], expected: true}") @TestParameters("{list: [5, 4, 3, 2, 1], subList: [1, 2, 3], expected: true}") @@ -186,6 +247,26 @@ public void contains_withMultiLevelNestedList_succeeds(String expression, boolea assertThat(result).isEqualTo(expected); } + @Test + @TestParameters("{expression: 'sets.contains([{1: 1}], [{1: 1}])', expected: true}") + @TestParameters("{expression: 'sets.contains([{1: 1}], [{1u: 1}, {1: 1.0}])', expected: true}") + @TestParameters( + "{expression: 'sets.contains([{\"a\": \"b\"}, {\"c\": \"d\"}], [{\"a\": \"b\"}])', expected:" + + " true}") + @TestParameters("{expression: 'sets.contains([{2: 1}], [{1: 1}])', expected: false}") + @TestParameters( + "{expression: 'sets.contains([{\"a\": \"b\"}], [{\"a\": \"b\"}, {\"c\": \"d\"}])', expected:" + + " false}") + public void contains_withMapValues_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + @Test @TestParameters("{expression: 'sets.equivalent([], [])', expected: true}") @TestParameters("{expression: 'sets.equivalent([1], [1])', expected: true}") @@ -212,6 +293,7 @@ public void equivalent_withIntTypes_succeeds(String expression, boolean expected @TestParameters("{expression: 'sets.equivalent([1], [1u, 1.0])', expected: true}") @TestParameters( "{expression: 'sets.equivalent([[1.0], [2, 3]], [[1], [2, 3.0]])', expected: true}") + @TestParameters("{expression: 'sets.equivalent([1, 2.0, 3], [1, 2])', expected: false}") @TestParameters("{expression: 'sets.equivalent([1, 2], [2u, 2, 2.0])', expected: false}") @TestParameters("{expression: 'sets.equivalent([1, 2], [1u, 2, 2.3])', expected: false}") public void equivalent_withMixedTypes_succeeds(String expression, boolean expected) @@ -224,6 +306,59 @@ public void equivalent_withMixedTypes_succeeds(String expression, boolean expect assertThat(result).isEqualTo(expected); } + @Test + @TestParameters( + "{expression: 'sets.equivalent([TestAllTypes{}, TestAllTypes{}], [TestAllTypes{}])'," + + " expected: true}") + @TestParameters( + "{expression: 'sets.equivalent([TestAllTypes{}], [TestAllTypes{}, TestAllTypes{}])'," + + " expected: true}") + @TestParameters( + "{expression: 'sets.equivalent([TestAllTypes{single_int64: 1, single_uint64: 2u}]," + + " [TestAllTypes{single_int64: 1, single_uint64: 2u}])', expected: true}") + @TestParameters( + "{expression: 'sets.equivalent([TestAllTypes{single_any: [1.0, 2u, 3]}]," + + " [TestAllTypes{single_any: [1u, 2, 3.0]}])', expected: true}") + @TestParameters( + "{expression: 'sets.equivalent([TestAllTypes{single_any: [1.0, 2u, 3]}," + + " TestAllTypes{single_any: [2,3,4]}], [TestAllTypes{single_any: [1u, 2, 3.0]}])'," + + " expected: false}") + @TestParameters( + "{expression: 'sets.equivalent([TestAllTypes{single_int64: 1, single_uint64: 2u}]," + + " [TestAllTypes{single_int64: 2, single_uint64: 3u}])', expected: false}") + public void equivalent_withProtoMessage_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + + @Test + @TestParameters("{expression: 'sets.equivalent([{1: 1}], [{1: 1}, {1: 1}])', expected: true}") + @TestParameters("{expression: 'sets.equivalent([{1: 1}, {1: 1}], [{1: 1}])', expected: true}") + @TestParameters("{expression: 'sets.equivalent([{1: 1}], [{1: 1u}, {1: 1.0}])', expected: true}") + @TestParameters( + "{expression: 'sets.equivalent([{1: 1}, {1u: 1}], [{1u: 1}, {1: 1.0}])', expected: true}") + @TestParameters( + "{expression: 'sets.equivalent([{\"a\": \"b\"}, {\"a\": \"b\"}], [{\"a\": \"b\"}])'," + + " expected: true}") + @TestParameters("{expression: 'sets.equivalent([{2: 1}], [{1: 1}])', expected: false}") + @TestParameters( + "{expression: 'sets.equivalent([{\"a\": \"b\"}], [{\"a\": \"b\"}, {\"c\": \"d\"}])'," + + " expected: false}") + public void equivalent_withMapValues_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + @Test @TestParameters("{expression: 'sets.intersects([], [])', expected: false}") @TestParameters("{expression: 'sets.intersects([1], [])', expected: false}") @@ -254,9 +389,62 @@ public void intersects_withMixedTypes_succeeds(String expression, boolean expect assertThat(result).isEqualTo(expected); } + @Test + @TestParameters("{expression: 'sets.intersects([{1: 1}], [{1: 1}, {1: 1}])', expected: true}") + @TestParameters("{expression: 'sets.intersects([{1: 1}, {1: 1}], [{1: 1}])', expected: true}") + @TestParameters("{expression: 'sets.intersects([{1: 1}], [{1: 1u}, {1: 1.0}])', expected: true}") + @TestParameters( + "{expression: 'sets.intersects([{1: 1}, {1u: 1}], [{1.0: 1u}, {1u: 1.0}])', expected: true}") + @TestParameters("{expression: 'sets.intersects([{1:2}], [{1:2}, {2:3}])', expected: true}") + @TestParameters( + "{expression: 'sets.intersects([{\"a\": \"b\"}, {\"a\": \"b\"}], [{\"a\": \"b\"}])'," + + " expected: true}") + @TestParameters( + "{expression: 'sets.intersects([{\"a\": \"b\"}], [{\"c\": \"d\"}])', expected: false}") + @TestParameters("{expression: 'sets.intersects([{2: 1}], [{1: 1}])', expected: false}") + public void intersects_withMapValues_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + + @Test + @TestParameters( + "{expression: 'sets.intersects([TestAllTypes{}, TestAllTypes{}], [TestAllTypes{}])'," + + " expected: true}") + @TestParameters( + "{expression: 'sets.intersects([TestAllTypes{}], [TestAllTypes{}, TestAllTypes{}])'," + + " expected: true}") + @TestParameters( + "{expression: 'sets.intersects([TestAllTypes{single_int64: 1, single_uint64: 2u}]," + + " [TestAllTypes{single_int64: 1, single_uint64: 2u}])', expected: true}") + @TestParameters( + "{expression: 'sets.intersects([TestAllTypes{single_any: [1.0, 2u, 3]}]," + + " [TestAllTypes{single_any: [1u, 2, 3.0]}])', expected: true}") + @TestParameters( + "{expression: 'sets.intersects([TestAllTypes{single_any: [1, 2, 3.5]}," + + " TestAllTypes{single_any: [2,3,4]}], [TestAllTypes{single_any: [1u, 2, 3.0]}])'," + + " expected: false}") + @TestParameters( + "{expression: 'sets.intersects([TestAllTypes{single_int64: 1, single_uint64: 2u}]," + + " [TestAllTypes{single_int64: 2, single_uint64: 3u}])', expected: false}") + public void intersects_withProtoMessage_succeeds(String expression, boolean expected) + throws Exception { + CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst(); + CelRuntime.Program program = RUNTIME.createProgram(ast); + + boolean result = (boolean) program.eval(); + + assertThat(result).isEqualTo(expected); + } + @Test public void setsExtension_containsFunctionSubset_succeeds() throws Exception { - CelSetsExtensions setsExtensions = CelExtensions.sets(Function.CONTAINS); + CelSetsExtensions setsExtensions = CelExtensions.sets(CelOptions.DEFAULT, Function.CONTAINS); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build(); CelRuntime celRuntime = @@ -270,7 +458,7 @@ public void setsExtension_containsFunctionSubset_succeeds() throws Exception { @Test public void setsExtension_equivalentFunctionSubset_succeeds() throws Exception { - CelSetsExtensions setsExtensions = CelExtensions.sets(Function.EQUIVALENT); + CelSetsExtensions setsExtensions = CelExtensions.sets(CelOptions.DEFAULT, Function.EQUIVALENT); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build(); CelRuntime celRuntime = @@ -286,7 +474,7 @@ public void setsExtension_equivalentFunctionSubset_succeeds() throws Exception { @Test public void setsExtension_intersectsFunctionSubset_succeeds() throws Exception { - CelSetsExtensions setsExtensions = CelExtensions.sets(Function.INTERSECTS); + CelSetsExtensions setsExtensions = CelExtensions.sets(CelOptions.DEFAULT, Function.INTERSECTS); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build(); CelRuntime celRuntime = @@ -302,7 +490,7 @@ public void setsExtension_intersectsFunctionSubset_succeeds() throws Exception { @Test public void setsExtension_compileUnallowedFunction_throws() { - CelSetsExtensions setsExtensions = CelExtensions.sets(Function.EQUIVALENT); + CelSetsExtensions setsExtensions = CelExtensions.sets(CelOptions.DEFAULT, Function.EQUIVALENT); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build(); @@ -313,12 +501,13 @@ public void setsExtension_compileUnallowedFunction_throws() { @Test public void setsExtension_evaluateUnallowedFunction_throws() throws Exception { - CelSetsExtensions setsExtensions = CelExtensions.sets(Function.CONTAINS, Function.EQUIVALENT); + CelSetsExtensions setsExtensions = + CelExtensions.sets(CelOptions.DEFAULT, Function.CONTAINS, Function.EQUIVALENT); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build(); CelRuntime celRuntime = CelRuntimeFactory.standardCelRuntimeBuilder() - .addLibraries(CelExtensions.sets(Function.EQUIVALENT)) + .addLibraries(CelExtensions.sets(CelOptions.DEFAULT, Function.EQUIVALENT)) .build(); CelAbstractSyntaxTree ast = celCompiler.compile("sets.contains([1, 2], [2])").getAst(); From 396ddcd66d7b1553c3630d7c17701eedfa87dc76 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Tue, 13 Aug 2024 09:26:17 -0700 Subject: [PATCH 13/33] Reduce count of errors joined together during parsing error PiperOrigin-RevId: 662544661 --- common/src/main/java/dev/cel/common/CelValidationException.java | 2 +- .../test/java/dev/cel/common/CelValidationExceptionTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/dev/cel/common/CelValidationException.java b/common/src/main/java/dev/cel/common/CelValidationException.java index 522706e83..953f5b152 100644 --- a/common/src/main/java/dev/cel/common/CelValidationException.java +++ b/common/src/main/java/dev/cel/common/CelValidationException.java @@ -22,7 +22,7 @@ public final class CelValidationException extends CelException { // Truncates all errors beyond this limit in the message. - private static final int MAX_ERRORS_TO_REPORT = 1000; + private static final int MAX_ERRORS_TO_REPORT = 500; private final CelSource source; private final ImmutableList errors; diff --git a/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java b/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java index be428a64c..8768616ea 100644 --- a/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java +++ b/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java @@ -37,6 +37,6 @@ public void construct_withLargeErrorCount() { assertThat(celValidationException.getErrors()).hasSize(1500); assertThat(celValidationException) .hasMessageThat() - .endsWith("...and 500 more errors (truncated)"); + .endsWith("...and 1000 more errors (truncated)"); } } From 233fda4b13e65494b6b2f8c2abb4fd02c671e75a Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Tue, 13 Aug 2024 10:25:49 -0700 Subject: [PATCH 14/33] Truncate joined compilation errors further to 100 PiperOrigin-RevId: 662565735 --- common/src/main/java/dev/cel/common/CelValidationException.java | 2 +- .../test/java/dev/cel/common/CelValidationExceptionTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/dev/cel/common/CelValidationException.java b/common/src/main/java/dev/cel/common/CelValidationException.java index 953f5b152..18bec2fe6 100644 --- a/common/src/main/java/dev/cel/common/CelValidationException.java +++ b/common/src/main/java/dev/cel/common/CelValidationException.java @@ -22,7 +22,7 @@ public final class CelValidationException extends CelException { // Truncates all errors beyond this limit in the message. - private static final int MAX_ERRORS_TO_REPORT = 500; + private static final int MAX_ERRORS_TO_REPORT = 100; private final CelSource source; private final ImmutableList errors; diff --git a/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java b/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java index 8768616ea..703531d81 100644 --- a/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java +++ b/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java @@ -37,6 +37,6 @@ public void construct_withLargeErrorCount() { assertThat(celValidationException.getErrors()).hasSize(1500); assertThat(celValidationException) .hasMessageThat() - .endsWith("...and 1000 more errors (truncated)"); + .endsWith("...and 1400 more errors (truncated)"); } } From 041886e2e9c3f85d89d5629bd318b67d1d8fe4b8 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Tue, 13 Aug 2024 11:56:11 -0700 Subject: [PATCH 15/33] Import only. PiperOrigin-RevId: 662600683 --- conformance/src/test/java/dev/cel/conformance/BUILD.bazel | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/conformance/src/test/java/dev/cel/conformance/BUILD.bazel b/conformance/src/test/java/dev/cel/conformance/BUILD.bazel index 5f1380277..6b60d77d4 100644 --- a/conformance/src/test/java/dev/cel/conformance/BUILD.bazel +++ b/conformance/src/test/java/dev/cel/conformance/BUILD.bazel @@ -97,8 +97,10 @@ _TESTS_TO_SKIP = [ "wrappers/duration/to_json", "wrappers/timestamp/to_json", "fields/qualified_identifier_resolution/map_value_repeat_key_heterogeneous", - # TODO: Add strings.quote. + # TODO: Add strings.format and strings.quote. "string_ext/quote", + "string_ext/format", + "string_ext/format_errors", # TODO: Fix null assignment to a field "proto2/set_null/single_message", From 595eccda94886956322be02ba6a88f1269f00148 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Tue, 13 Aug 2024 13:32:56 -0700 Subject: [PATCH 16/33] Change cel_spec repo url to 0.16.0 in WORKSPACE PiperOrigin-RevId: 662633046 --- WORKSPACE | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 04efe6010..9ba1c3f0c 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -149,10 +149,10 @@ http_archive( # cel-spec api/expr canonical protos http_archive( name = "cel_spec", - sha256 = "65a153c1c4d73a135c364a4955e6aabd1093f0ed291774d3637f350504505085", - strip_prefix = "cel-spec-0789389e13a0626ec3521e4f109acce360565ce6", + sha256 = "b4efed0586004c538fe2be4f0472a1e2483790895493502fcab58f56060f6d37", + strip_prefix = "cel-spec-0.16.0", urls = [ - "https://github.com/google/cel-spec/archive/0789389e13a0626ec3521e4f109acce360565ce6.tar.gz", + "https://github.com/google/cel-spec/archive/refs/tags/v0.16.0.tar.gz", ], ) From 83fe5a312bc60539d5072840c2bb817034391c12 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 14 Aug 2024 10:42:21 -0700 Subject: [PATCH 17/33] Parse explanations in match blocks PiperOrigin-RevId: 662975534 --- .../main/java/dev/cel/policy/CelPolicy.java | 7 ++++ .../dev/cel/policy/CelPolicyYamlParser.java | 18 +++++++++ .../cel/policy/CelPolicyYamlParserTest.java | 38 +++++++++++++++++++ .../test/resources/nested_rule/policy.yaml | 2 +- 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/policy/src/main/java/dev/cel/policy/CelPolicy.java b/policy/src/main/java/dev/cel/policy/CelPolicy.java index 45a2c666c..0f2f5d1a8 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicy.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicy.java @@ -159,6 +159,9 @@ public abstract static class Match { public abstract Result result(); + /** Explanation returns the explanation expression, or empty expression if output is not set. */ + public abstract Optional explanation(); + /** Encapsulates the result of this match when condition is met. (either an output or a rule) */ @AutoOneOf(Match.Result.Kind.class) public abstract static class Result { @@ -191,8 +194,12 @@ public abstract static class Builder implements RequiredFieldsChecker { public abstract Builder setResult(Result result); + public abstract Builder setExplanation(ValueString explanation); + abstract Optional result(); + abstract Optional explanation(); + @Override public ImmutableList requiredFields() { return ImmutableList.of(RequiredField.of("output or a rule", this::result)); diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java b/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java index 541dfdfb3..1327fbcef 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java @@ -202,12 +202,30 @@ public CelPolicy.Match parseMatch( result -> ctx.reportError(tagId, "Only the rule or the output may be set")); matchBuilder.setResult(Match.Result.ofOutput(ctx.newValueString(value))); break; + case "explanation": + matchBuilder + .result() + .filter(result -> result.kind().equals(Match.Result.Kind.RULE)) + .ifPresent( + result -> + ctx.reportError( + tagId, + "Explanation can only be set on output match cases, not nested rules")); + matchBuilder.setExplanation(ctx.newValueString(value)); + break; case "rule": matchBuilder .result() .filter(result -> result.kind().equals(Match.Result.Kind.OUTPUT)) .ifPresent( result -> ctx.reportError(tagId, "Only the rule or the output may be set")); + matchBuilder + .explanation() + .ifPresent( + result -> + ctx.reportError( + result.id(), + "Explanation can only be set on output match cases, not nested rules")); matchBuilder.setResult(Match.Result.ofRule(parseRule(ctx, policyBuilder, value))); break; default: diff --git a/policy/src/test/java/dev/cel/policy/CelPolicyYamlParserTest.java b/policy/src/test/java/dev/cel/policy/CelPolicyYamlParserTest.java index 5bc90cfb9..c648d3ac3 100644 --- a/policy/src/test/java/dev/cel/policy/CelPolicyYamlParserTest.java +++ b/policy/src/test/java/dev/cel/policy/CelPolicyYamlParserTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.common.collect.Iterables; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import dev.cel.policy.PolicyTestHelper.K8sTagHandler; @@ -42,6 +43,21 @@ public void parseYamlPolicy_success(@TestParameter TestYamlPolicy yamlPolicy) th assertThat(policy.policySource().getDescription()).isEqualTo(description); } + @Test + public void parseYamlPolicy_withExplanation() throws Exception { + String policySource = + "rule:\n" + + " match:\n" + + " - output: 'true'\n" + + " explanation: \"'custom explanation'\""; + + CelPolicy policy = POLICY_PARSER.parse(policySource); + + assertThat(policy.rule().matches()).hasSize(1); + assertThat(Iterables.getOnlyElement(policy.rule().matches()).explanation()) + .hasValue(ValueString.of(11, "'custom explanation'")); + } + @Test public void parseYamlPolicy_errors(@TestParameter PolicyParseErrorTestCase testCase) { CelPolicyValidationException e = @@ -197,6 +213,28 @@ private enum PolicyParseErrorTestCase { "ERROR: :7:7: Only the rule or the output may be set\n" + " | output: \"world\"\n" + " | ......^"), + MATCH_NESTED_RULE_SET_THEN_EXPLANATION( + "rule:\n" + + " match:\n" + + " - condition: \"true\"\n" + + " rule:\n" + + " match:\n" + + " - output: \"hello\"\n" + + " explanation: \"foo\"", + "ERROR: :7:7: Explanation can only be set on output match cases, not nested rules\n" + + " | explanation: \"foo\"\n" + + " | ......^"), + MATCH_EXPLANATION_SET_THEN_NESTED_RULE( + "rule:\n" + + " match:\n" + + " - condition: \"true\"\n" + + " explanation: \"foo\"\n" + + " rule:\n" + + " match:\n" + + " - output: \"hello\"\n", + "ERROR: :4:21: Explanation can only be set on output match cases, not nested rules\n" + + " | explanation: \"foo\"\n" + + " | ....................^"), INVALID_ROOT_NODE_TYPE( "- rule:\n" + " id: a", "ERROR: :1:1: Got yaml node type tag:yaml.org,2002:seq, wanted type(s)" diff --git a/policy/src/test/resources/nested_rule/policy.yaml b/policy/src/test/resources/nested_rule/policy.yaml index bbbfe0fc1..2fc566b85 100644 --- a/policy/src/test/resources/nested_rule/policy.yaml +++ b/policy/src/test/resources/nested_rule/policy.yaml @@ -35,4 +35,4 @@ rule: - condition: resource.origin in variables.permitted_regions output: "{'banned': false}" - output: "{'banned': true}" - + explanation: "'resource is in the banned region ' + resource.origin" \ No newline at end of file From 80d29a99886eeb04536ba6279c4e412fa4fd36cf Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 14 Aug 2024 17:42:09 -0700 Subject: [PATCH 18/33] Improved support for nested rules PiperOrigin-RevId: 663114054 --- .../src/main/java/dev/cel/policy/BUILD.bazel | 2 +- .../java/dev/cel/policy/CelCompiledRule.java | 30 ++++++++++++ .../java/dev/cel/policy/RuleComposer.java | 28 +++++++---- .../java/dev/cel/policy/PolicyTestHelper.java | 20 ++++++++ .../test/resources/nested_rule2/config.yaml | 22 +++++++++ .../test/resources/nested_rule2/policy.yaml | 40 ++++++++++++++++ .../test/resources/nested_rule2/tests.yaml | 48 +++++++++++++++++++ .../test/resources/nested_rule3/config.yaml | 22 +++++++++ .../test/resources/nested_rule3/policy.yaml | 39 +++++++++++++++ .../test/resources/nested_rule3/tests.yaml | 48 +++++++++++++++++++ 10 files changed, 288 insertions(+), 11 deletions(-) create mode 100644 policy/src/test/resources/nested_rule2/config.yaml create mode 100644 policy/src/test/resources/nested_rule2/policy.yaml create mode 100644 policy/src/test/resources/nested_rule2/tests.yaml create mode 100644 policy/src/test/resources/nested_rule3/config.yaml create mode 100644 policy/src/test/resources/nested_rule3/policy.yaml create mode 100644 policy/src/test/resources/nested_rule3/tests.yaml diff --git a/policy/src/main/java/dev/cel/policy/BUILD.bazel b/policy/src/main/java/dev/cel/policy/BUILD.bazel index 15e2977c2..ea3f4353c 100644 --- a/policy/src/main/java/dev/cel/policy/BUILD.bazel +++ b/policy/src/main/java/dev/cel/policy/BUILD.bazel @@ -227,6 +227,7 @@ java_library( "//bundle:cel", "//common", "//common:compiler_common", + "//common/ast", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], @@ -304,7 +305,6 @@ java_library( "//common", "//common:compiler_common", "//common:mutable_ast", - "//common/ast", "//extensions:optional_library", "//optimizer:ast_optimizer", "//optimizer:mutable_ast", diff --git a/policy/src/main/java/dev/cel/policy/CelCompiledRule.java b/policy/src/main/java/dev/cel/policy/CelCompiledRule.java index 3c5893dfb..a055cc4d3 100644 --- a/policy/src/main/java/dev/cel/policy/CelCompiledRule.java +++ b/policy/src/main/java/dev/cel/policy/CelCompiledRule.java @@ -20,6 +20,8 @@ import dev.cel.bundle.Cel; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelVarDecl; +import dev.cel.common.ast.CelConstant; +import dev.cel.common.ast.CelExpr; import java.util.Optional; /** @@ -36,6 +38,28 @@ public abstract class CelCompiledRule { public abstract Cel cel(); + /** + * HasOptionalOutput returns whether the rule returns a concrete or optional value. The rule may + * return an optional value if all match expressions under the rule are conditional. + */ + public boolean hasOptionalOutput() { + boolean isOptionalOutput = false; + for (CelCompiledMatch match : matches()) { + if (match.result().kind().equals(CelCompiledMatch.Result.Kind.RULE) + && match.result().rule().hasOptionalOutput()) { + return true; + } + + if (match.isConditionLiteral()) { + return false; + } + + isOptionalOutput = true; + } + + return isOptionalOutput; + } + /** * A compiled policy variable (ex: variables.foo). Note that this is not the same thing as the * variables declared in the config. @@ -63,6 +87,12 @@ public abstract static class CelCompiledMatch { public abstract Result result(); + public boolean isConditionLiteral() { + CelExpr celExpr = condition().getExpr(); + return celExpr.constantOrDefault().getKind().equals(CelConstant.Kind.BOOLEAN_VALUE) + && celExpr.constant().booleanValue(); + } + /** Encapsulates the result of this match when condition is met. (either an output or a rule) */ @AutoOneOf(CelCompiledMatch.Result.Kind.class) public abstract static class Result { diff --git a/policy/src/main/java/dev/cel/policy/RuleComposer.java b/policy/src/main/java/dev/cel/policy/RuleComposer.java index 42b1b7af2..e53c5f34d 100644 --- a/policy/src/main/java/dev/cel/policy/RuleComposer.java +++ b/policy/src/main/java/dev/cel/policy/RuleComposer.java @@ -24,7 +24,6 @@ import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelMutableAst; import dev.cel.common.CelValidationException; -import dev.cel.common.ast.CelConstant.Kind; import dev.cel.extensions.CelOptionalLibrary.Function; import dev.cel.optimizer.AstMutator; import dev.cel.optimizer.CelAstOptimizer; @@ -75,10 +74,14 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul long lastOutputId = 0; for (CelCompiledMatch match : Lists.reverse(compiledRule.matches())) { CelAbstractSyntaxTree conditionAst = match.condition(); - boolean isTriviallyTrue = - conditionAst.getExpr().constantOrDefault().getKind().equals(Kind.BOOLEAN_VALUE) - && conditionAst.getExpr().constant().booleanValue(); + // If the condition is trivially true, none of the matches in the rule causes the result + // to become optional, and the rule is not the last match, then this will introduce + // unreachable outputs or rules. + boolean isTriviallyTrue = match.isConditionLiteral(); + switch (match.result().kind()) { + // For the match's output, determine whether the output should be wrapped + // into an optional value, a conditional, or both. case OUTPUT: OutputValue matchOutput = match.result().output(); CelMutableAst outAst = CelMutableAst.fromCelAst(matchOutput.ast()); @@ -107,21 +110,25 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul lastOutputId = matchOutput.sourceId(); continue; case RULE: + // If the match has a nested rule, then compute the rule and whether it has + // an optional return value. CelCompiledRule matchNestedRule = match.result().rule(); RuleOptimizationResult nestedRule = optimizeRule(cel, matchNestedRule); + boolean nestedHasOptional = matchNestedRule.hasOptionalOutput(); CelMutableAst nestedRuleAst = nestedRule.ast(); - if (isOptionalResult && !nestedRule.isOptionalResult()) { + if (isOptionalResult && !nestedHasOptional) { nestedRuleAst = astMutator.newGlobalCall(Function.OPTIONAL_OF.getFunction(), nestedRuleAst); } - if (!isOptionalResult && nestedRule.isOptionalResult()) { + if (!isOptionalResult && nestedHasOptional) { matchAst = astMutator.newGlobalCall(Function.OPTIONAL_OF.getFunction(), matchAst); isOptionalResult = true; } - if (!isOptionalResult && !nestedRule.isOptionalResult()) { - throw new IllegalArgumentException("Subrule early terminates policy"); - } - if (isTriviallyTrue) { + // If either the nested rule or current condition output are optional then + // use optional.or() to specify the combination of the first and second results + // Note, the argument order is reversed due to the traversal of matches in + // reverse order. + if (isOptionalResult && isTriviallyTrue) { matchAst = astMutator.newMemberCall(nestedRuleAst, Function.OR.getFunction(), matchAst); } else { matchAst = @@ -131,6 +138,7 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul nestedRuleAst, matchAst); } + assertComposedAstIsValid( cel, matchAst, diff --git a/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java index a41f398d1..e0c490f03 100644 --- a/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java +++ b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java @@ -48,6 +48,26 @@ enum TestYamlPolicy { + "? optional.of({\"banned\": true}) : optional.none()).or(" + "optional.of((resource.origin in variables.permitted_regions)" + " ? {\"banned\": false} : {\"banned\": true})))"), + NESTED_RULE2( + "nested_rule2", + false, + "cel.bind(variables.permitted_regions, [\"us\", \"uk\", \"es\"]," + + " resource.?user.orValue(\"\").startsWith(\"bad\") ?" + + " cel.bind(variables.banned_regions, {\"us\": false, \"ru\": false, \"ir\": false}," + + " (resource.origin in variables.banned_regions && !(resource.origin in" + + " variables.permitted_regions)) ? {\"banned\": \"restricted_region\"} : {\"banned\":" + + " \"bad_actor\"}) : (!(resource.origin in variables.permitted_regions) ? {\"banned\":" + + " \"unconfigured_region\"} : {}))"), + NESTED_RULE3( + "nested_rule3", + true, + "cel.bind(variables.permitted_regions, [\"us\", \"uk\", \"es\"]," + + " resource.?user.orValue(\"\").startsWith(\"bad\") ?" + + " optional.of(cel.bind(variables.banned_regions, {\"us\": false, \"ru\": false," + + " \"ir\": false}, (resource.origin in variables.banned_regions && !(resource.origin" + + " in variables.permitted_regions)) ? {\"banned\": \"restricted_region\"} :" + + " {\"banned\": \"bad_actor\"})) : (!(resource.origin in variables.permitted_regions)" + + " ? optional.of({\"banned\": \"unconfigured_region\"}) : optional.none()))"), REQUIRED_LABELS( "required_labels", true, diff --git a/policy/src/test/resources/nested_rule2/config.yaml b/policy/src/test/resources/nested_rule2/config.yaml new file mode 100644 index 000000000..9ee6f0e49 --- /dev/null +++ b/policy/src/test/resources/nested_rule2/config.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: "nested_rule2" +variables: +- name: "resource" + type: + type_name: "map" + params: + - type_name: "string" + - type_name: "dyn" \ No newline at end of file diff --git a/policy/src/test/resources/nested_rule2/policy.yaml b/policy/src/test/resources/nested_rule2/policy.yaml new file mode 100644 index 000000000..fef91869f --- /dev/null +++ b/policy/src/test/resources/nested_rule2/policy.yaml @@ -0,0 +1,40 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: nested_rule2 +rule: + variables: + - name: "permitted_regions" + expression: "['us', 'uk', 'es']" + match: + - condition: resource.?user.orValue("").startsWith("bad") + rule: + id: "banned regions" + description: > + determine whether the resource origin is in the banned + list. If the region is also in the permitted list, the + ban has no effect. + variables: + - name: "banned_regions" + expression: "{'us': false, 'ru': false, 'ir': false}" + match: + - condition: | + resource.origin in variables.banned_regions && + !(resource.origin in variables.permitted_regions) + output: "{'banned': 'restricted_region'}" + explanation: "'resource is in the banned region ' + resource.origin" + - output: "{'banned': 'bad_actor'}" + - condition: "!(resource.origin in variables.permitted_regions)" + output: "{'banned': 'unconfigured_region'}" + - output: "{}" \ No newline at end of file diff --git a/policy/src/test/resources/nested_rule2/tests.yaml b/policy/src/test/resources/nested_rule2/tests.yaml new file mode 100644 index 000000000..b5fbba745 --- /dev/null +++ b/policy/src/test/resources/nested_rule2/tests.yaml @@ -0,0 +1,48 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +description: Nested rule conformance tests +section: +- name: "banned" + tests: + - name: "restricted_origin" + input: + resource: + value: + user: "bad-user" + origin: "ir" + output: "{'banned': 'restricted_region'}" + - name: "by_default" + input: + resource: + value: + user: "bad-user" + origin: "de" + output: "{'banned': 'bad_actor'}" + - name: "unconfigured_region" + input: + resource: + value: + user: "good-user" + origin: "de" + output: "{'banned': 'unconfigured_region'}" +- name: "permitted" + tests: + - name: "valid_origin" + input: + resource: + value: + user: "good-user" + origin: "uk" + output: "{}" \ No newline at end of file diff --git a/policy/src/test/resources/nested_rule3/config.yaml b/policy/src/test/resources/nested_rule3/config.yaml new file mode 100644 index 000000000..d9360d5c9 --- /dev/null +++ b/policy/src/test/resources/nested_rule3/config.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: "nested_rule3" +variables: +- name: "resource" + type: + type_name: "map" + params: + - type_name: "string" + - type_name: "dyn" \ No newline at end of file diff --git a/policy/src/test/resources/nested_rule3/policy.yaml b/policy/src/test/resources/nested_rule3/policy.yaml new file mode 100644 index 000000000..4ad765c8d --- /dev/null +++ b/policy/src/test/resources/nested_rule3/policy.yaml @@ -0,0 +1,39 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: nested_rule3 +rule: + variables: + - name: "permitted_regions" + expression: "['us', 'uk', 'es']" + match: + - condition: resource.?user.orValue("").startsWith("bad") + rule: + id: "banned regions" + description: > + determine whether the resource origin is in the banned + list. If the region is also in the permitted list, the + ban has no effect. + variables: + - name: "banned_regions" + expression: "{'us': false, 'ru': false, 'ir': false}" + match: + - condition: | + resource.origin in variables.banned_regions && + !(resource.origin in variables.permitted_regions) + output: "{'banned': 'restricted_region'}" + explanation: "'resource is in the banned region ' + resource.origin" + - output: "{'banned': 'bad_actor'}" + - condition: "!(resource.origin in variables.permitted_regions)" + output: "{'banned': 'unconfigured_region'}" \ No newline at end of file diff --git a/policy/src/test/resources/nested_rule3/tests.yaml b/policy/src/test/resources/nested_rule3/tests.yaml new file mode 100644 index 000000000..b10785d0c --- /dev/null +++ b/policy/src/test/resources/nested_rule3/tests.yaml @@ -0,0 +1,48 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +description: Nested rule conformance tests +section: +- name: "banned" + tests: + - name: "restricted_origin" + input: + resource: + value: + user: "bad-user" + origin: "ir" + output: "{'banned': 'restricted_region'}" + - name: "by_default" + input: + resource: + value: + user: "bad-user" + origin: "de" + output: "{'banned': 'bad_actor'}" + - name: "unconfigured_region" + input: + resource: + value: + user: "good-user" + origin: "de" + output: "{'banned': 'unconfigured_region'}" +- name: "permitted" + tests: + - name: "valid_origin" + input: + resource: + value: + user: "good-user" + origin: "uk" + output: "optional.none()" \ No newline at end of file From 89ea79c14d06146ff088a12f0fd6dd0b0c762ebf Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 14 Aug 2024 18:08:41 -0700 Subject: [PATCH 19/33] Add unreachable checks in policies PiperOrigin-RevId: 663120461 --- .../java/dev/cel/policy/CelCompiledRule.java | 22 +++++--- .../main/java/dev/cel/policy/CelPolicy.java | 21 +++++--- .../dev/cel/policy/CelPolicyCompilerImpl.java | 34 +++++++++++- .../dev/cel/policy/CelPolicyYamlParser.java | 8 +-- .../java/dev/cel/policy/RuleComposer.java | 4 +- .../cel/policy/CelPolicyCompilerImplTest.java | 3 +- .../resources/errors_unreachable/config.yaml | 54 +++++++++++++++++++ .../expected_errors.baseline | 6 +++ .../resources/errors_unreachable/policy.yaml | 39 ++++++++++++++ 9 files changed, 169 insertions(+), 22 deletions(-) create mode 100644 policy/src/test/resources/errors_unreachable/config.yaml create mode 100644 policy/src/test/resources/errors_unreachable/expected_errors.baseline create mode 100644 policy/src/test/resources/errors_unreachable/policy.yaml diff --git a/policy/src/main/java/dev/cel/policy/CelCompiledRule.java b/policy/src/main/java/dev/cel/policy/CelCompiledRule.java index a055cc4d3..57914232f 100644 --- a/policy/src/main/java/dev/cel/policy/CelCompiledRule.java +++ b/policy/src/main/java/dev/cel/policy/CelCompiledRule.java @@ -30,7 +30,11 @@ */ @AutoValue public abstract class CelCompiledRule { - public abstract Optional id(); + + /** Source metadata identifier associated with the compiled rule. */ + public abstract long sourceId(); + + public abstract Optional ruleId(); public abstract ImmutableList variables(); @@ -50,7 +54,7 @@ public boolean hasOptionalOutput() { return true; } - if (match.isConditionLiteral()) { + if (match.isConditionTriviallyTrue()) { return false; } @@ -83,11 +87,14 @@ static CelCompiledVariable create( /** A compiled Match. */ @AutoValue public abstract static class CelCompiledMatch { + /** Source metadata identifier associated with the compiled match. */ + public abstract long sourceId(); + public abstract CelAbstractSyntaxTree condition(); public abstract Result result(); - public boolean isConditionLiteral() { + public boolean isConditionTriviallyTrue() { CelExpr celExpr = condition().getExpr(); return celExpr.constantOrDefault().getKind().equals(CelConstant.Kind.BOOLEAN_VALUE) && celExpr.constant().booleanValue(); @@ -136,16 +143,17 @@ public static OutputValue create(long id, CelAbstractSyntaxTree ast) { } static CelCompiledMatch create( - CelAbstractSyntaxTree condition, CelCompiledMatch.Result result) { - return new AutoValue_CelCompiledRule_CelCompiledMatch(condition, result); + long sourceId, CelAbstractSyntaxTree condition, CelCompiledMatch.Result result) { + return new AutoValue_CelCompiledRule_CelCompiledMatch(sourceId, condition, result); } } static CelCompiledRule create( - Optional id, + long sourceId, + Optional ruleId, ImmutableList variables, ImmutableList matches, Cel cel) { - return new AutoValue_CelCompiledRule(id, variables, matches, cel); + return new AutoValue_CelCompiledRule(sourceId, ruleId, variables, matches, cel); } } diff --git a/policy/src/main/java/dev/cel/policy/CelPolicy.java b/policy/src/main/java/dev/cel/policy/CelPolicy.java index 0f2f5d1a8..33940c692 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicy.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicy.java @@ -45,7 +45,7 @@ public abstract class CelPolicy { public static Builder newBuilder() { return new AutoValue_CelPolicy.Builder() .setName(ValueString.of(0, "")) - .setRule(Rule.newBuilder().build()) + .setRule(Rule.newBuilder(0).build()) .setMetadata(ImmutableMap.of()); } @@ -86,8 +86,9 @@ public Builder putMetadata(Map map) { */ @AutoValue public abstract static class Rule { + public abstract long id(); - public abstract Optional id(); + public abstract Optional ruleId(); public abstract Optional description(); @@ -96,8 +97,9 @@ public abstract static class Rule { public abstract ImmutableSet matches(); /** Builder for {@link Rule}. */ - public static Builder newBuilder() { + public static Builder newBuilder(long id) { return new AutoValue_CelPolicy_Rule.Builder() + .setId(id) .setVariables(ImmutableSet.of()) .setMatches(ImmutableSet.of()); } @@ -106,7 +108,7 @@ public static Builder newBuilder() { @AutoValue.Builder public abstract static class Builder { - public abstract Rule.Builder setId(ValueString id); + public abstract Rule.Builder setRuleId(ValueString id); public abstract Rule.Builder setDescription(ValueString description); @@ -118,6 +120,8 @@ public abstract static class Builder { abstract ImmutableSet.Builder matchesBuilder(); + abstract Builder setId(long value); + @CanIgnoreReturnValue public Builder addVariables(Variable... variables) { return addVariables(Arrays.asList(variables)); @@ -159,6 +163,8 @@ public abstract static class Match { public abstract Result result(); + public abstract long id(); + /** Explanation returns the explanation expression, or empty expression if output is not set. */ public abstract Optional explanation(); @@ -189,6 +195,7 @@ public enum Kind { /** Builder for {@link Match}. */ @AutoValue.Builder public abstract static class Builder implements RequiredFieldsChecker { + public abstract Builder setId(long value); public abstract Builder setCondition(ValueString condition); @@ -196,6 +203,8 @@ public abstract static class Builder implements RequiredFieldsChecker { public abstract Builder setExplanation(ValueString explanation); + abstract Optional id(); + abstract Optional result(); abstract Optional explanation(); @@ -209,8 +218,8 @@ public ImmutableList requiredFields() { } /** Creates a new builder to construct a {@link Match} instance. */ - public static Builder newBuilder() { - return new AutoValue_CelPolicy_Match.Builder(); + public static Builder newBuilder(long id) { + return new AutoValue_CelPolicy_Match.Builder().setId(id); } } diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java b/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java index 8ca38dad4..b7d1377b1 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java @@ -35,6 +35,7 @@ import dev.cel.optimizer.CelOptimizerFactory; import dev.cel.policy.CelCompiledRule.CelCompiledMatch; import dev.cel.policy.CelCompiledRule.CelCompiledMatch.Result; +import dev.cel.policy.CelCompiledRule.CelCompiledMatch.Result.Kind; import dev.cel.policy.CelCompiledRule.CelCompiledVariable; import dev.cel.policy.CelPolicy.Match; import dev.cel.policy.CelPolicy.Variable; @@ -167,10 +168,39 @@ private CelCompiledRule compileRuleImpl( throw new IllegalArgumentException("Unexpected kind: " + match.result().kind()); } - matchBuilder.add(CelCompiledMatch.create(conditionAst, matchResult)); + matchBuilder.add(CelCompiledMatch.create(match.id(), conditionAst, matchResult)); } - return CelCompiledRule.create(rule.id(), variableBuilder.build(), matchBuilder.build(), cel); + CelCompiledRule compiledRule = + CelCompiledRule.create( + rule.id(), rule.ruleId(), variableBuilder.build(), matchBuilder.build(), cel); + + // Validate that all branches in the policy are reachable + checkUnreachableCode(compiledRule, compilerContext); + + return compiledRule; + } + + private void checkUnreachableCode(CelCompiledRule compiledRule, CompilerContext compilerContext) { + boolean ruleHasOptional = compiledRule.hasOptionalOutput(); + ImmutableList compiledMatches = compiledRule.matches(); + int matchCount = compiledMatches.size(); + for (int i = matchCount - 1; i >= 0; i--) { + CelCompiledMatch compiledMatch = compiledMatches.get(i); + boolean isTriviallyTrue = compiledMatch.isConditionTriviallyTrue(); + + if (isTriviallyTrue && !ruleHasOptional && i != matchCount - 1) { + if (compiledMatch.result().kind().equals(Kind.OUTPUT)) { + compilerContext.addIssue( + compiledMatch.sourceId(), + CelIssue.formatError(1, 0, "Match creates unreachable outputs")); + } else { + compilerContext.addIssue( + compiledMatch.result().rule().sourceId(), + CelIssue.formatError(1, 0, "Rule creates unreachable outputs")); + } + } + } } private static CelAbstractSyntaxTree newErrorAst() { diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java b/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java index 1327fbcef..318f44fbc 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java @@ -40,7 +40,7 @@ final class CelPolicyYamlParser implements CelPolicyParser { // Sentinel values for parsing errors private static final ValueString ERROR_VALUE = ValueString.newBuilder().setValue(ERROR).build(); private static final Match ERROR_MATCH = - Match.newBuilder().setCondition(ERROR_VALUE).setResult(Result.ofOutput(ERROR_VALUE)).build(); + Match.newBuilder(0).setCondition(ERROR_VALUE).setResult(Result.ofOutput(ERROR_VALUE)).build(); private static final Variable ERROR_VARIABLE = Variable.newBuilder().setExpression(ERROR_VALUE).setName(ERROR_VALUE).build(); @@ -122,7 +122,7 @@ public CelPolicy parsePolicy(PolicyParserContext ctx, Node node) { public CelPolicy.Rule parseRule( PolicyParserContext ctx, CelPolicy.Builder policyBuilder, Node node) { long valueId = ctx.collectMetadata(node); - CelPolicy.Rule.Builder ruleBuilder = CelPolicy.Rule.newBuilder(); + CelPolicy.Rule.Builder ruleBuilder = CelPolicy.Rule.newBuilder(valueId); if (!assertYamlType(ctx, valueId, node, YamlNodeType.MAP)) { return ruleBuilder.build(); } @@ -137,7 +137,7 @@ public CelPolicy.Rule parseRule( Node value = nodeTuple.getValueNode(); switch (fieldName) { case "id": - ruleBuilder.setId(ctx.newValueString(value)); + ruleBuilder.setRuleId(ctx.newValueString(value)); break; case "description": ruleBuilder.setDescription(ctx.newValueString(value)); @@ -181,7 +181,7 @@ public CelPolicy.Match parseMatch( } MappingNode matchNode = (MappingNode) node; CelPolicy.Match.Builder matchBuilder = - CelPolicy.Match.newBuilder().setCondition(ValueString.of(ctx.nextId(), "true")); + CelPolicy.Match.newBuilder(nodeId).setCondition(ValueString.of(ctx.nextId(), "true")); for (NodeTuple nodeTuple : matchNode.getValue()) { Node key = nodeTuple.getKeyNode(); long tagId = ctx.collectMetadata(key); diff --git a/policy/src/main/java/dev/cel/policy/RuleComposer.java b/policy/src/main/java/dev/cel/policy/RuleComposer.java index e53c5f34d..814dc8f8a 100644 --- a/policy/src/main/java/dev/cel/policy/RuleComposer.java +++ b/policy/src/main/java/dev/cel/policy/RuleComposer.java @@ -77,7 +77,7 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul // If the condition is trivially true, none of the matches in the rule causes the result // to become optional, and the rule is not the last match, then this will introduce // unreachable outputs or rules. - boolean isTriviallyTrue = match.isConditionLiteral(); + boolean isTriviallyTrue = match.isConditionTriviallyTrue(); switch (match.result().kind()) { // For the match's output, determine whether the output should be wrapped @@ -144,7 +144,7 @@ private RuleOptimizationResult optimizeRule(Cel cel, CelCompiledRule compiledRul matchAst, String.format( "failed composing the subrule '%s' due to conflicting output types.", - matchNestedRule.id().map(ValueString::value).orElse("")), + matchNestedRule.ruleId().map(ValueString::value).orElse("")), lastOutputId); break; } diff --git a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java index 30915be4a..7d4bb85d1 100644 --- a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java +++ b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java @@ -308,7 +308,8 @@ private enum MultilineErrorTest { private enum TestErrorYamlPolicy { COMPILE_ERRORS("compile_errors"), COMPOSE_ERRORS_CONFLICTING_OUTPUT("compose_errors_conflicting_output"), - COMPOSE_ERRORS_CONFLICTING_SUBRULE("compose_errors_conflicting_subrule"); + COMPOSE_ERRORS_CONFLICTING_SUBRULE("compose_errors_conflicting_subrule"), + ERRORS_UNREACHABLE("errors_unreachable"); private final String name; private final String policyFilePath; diff --git a/policy/src/test/resources/errors_unreachable/config.yaml b/policy/src/test/resources/errors_unreachable/config.yaml new file mode 100644 index 000000000..8f79bb763 --- /dev/null +++ b/policy/src/test/resources/errors_unreachable/config.yaml @@ -0,0 +1,54 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: "errors_unreachable" +extensions: +- name: "sets" +- name: "strings" + version: "latest" +variables: +- name: "destination.ip" + type: + type_name: "string" +- name: "origin.ip" + type: + type_name: "string" +- name: "spec.restricted_destinations" + type: + type_name: "list" + params: + - type_name: "string" +- name: "spec.origin" + type: + type_name: "string" +- name: "request" + type: + type_name: "map" + params: + - type_name: "string" + - type_name: "dyn" +- name: "resource" + type: + type_name: "map" + params: + - type_name: "string" + - type_name: "dyn" +functions: +- name: "locationCode" + overloads: + - id: "locationCode_string" + args: + - type_name: "string" + return: + type_name: "string" diff --git a/policy/src/test/resources/errors_unreachable/expected_errors.baseline b/policy/src/test/resources/errors_unreachable/expected_errors.baseline new file mode 100644 index 000000000..f5f24acbe --- /dev/null +++ b/policy/src/test/resources/errors_unreachable/expected_errors.baseline @@ -0,0 +1,6 @@ +ERROR: errors_unreachable/policy.yaml:36:9: Match creates unreachable outputs + | - output: | + | ........^ +ERROR: errors_unreachable/policy.yaml:28:7: Rule creates unreachable outputs + | match: + | ......^ \ No newline at end of file diff --git a/policy/src/test/resources/errors_unreachable/policy.yaml b/policy/src/test/resources/errors_unreachable/policy.yaml new file mode 100644 index 000000000..f43fd62c7 --- /dev/null +++ b/policy/src/test/resources/errors_unreachable/policy.yaml @@ -0,0 +1,39 @@ +# Copyright 2024 Google LLC +# +# Licensed 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 +# +# https://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. + +name: "errors_unreachable" +rule: + variables: + - name: want + expression: request.labels + - name: missing + expression: variables.want.filter(l, !(l in resource.labels)) + - name: invalid + expression: > + resource.labels.filter(l, + l in variables.want && variables.want[l] != resource.labels[l]) + match: + - rule: + match: + - output: "''" + - condition: variables.missing.size() > 0 + output: | + "missing one or more required labels: [\"" + variables.missing.join(',') + "\"]" + - condition: variables.invalid.size() > 0 + rule: + match: + - output: | + "invalid values provided on one or more labels: [\"" + variables.invalid.join(',') + "\"]" + - condition: "false" + output: "'unreachable'" From 12d777fda94c6cf63a547ff360c42c39b5583f46 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 14 Aug 2024 19:45:09 -0700 Subject: [PATCH 20/33] Add a validator for enforcing AST depth limit PiperOrigin-RevId: 663141870 --- .../validators/AstDepthLimitValidator.java | 69 +++++++++++ .../dev/cel/validator/validators/BUILD.bazel | 15 +++ .../AstDepthLimitValidatorTest.java | 112 ++++++++++++++++++ .../dev/cel/validator/validators/BUILD.bazel | 2 + validator/validators/BUILD.bazel | 5 + 5 files changed, 203 insertions(+) create mode 100644 validator/src/main/java/dev/cel/validator/validators/AstDepthLimitValidator.java create mode 100644 validator/src/test/java/dev/cel/validator/validators/AstDepthLimitValidatorTest.java diff --git a/validator/src/main/java/dev/cel/validator/validators/AstDepthLimitValidator.java b/validator/src/main/java/dev/cel/validator/validators/AstDepthLimitValidator.java new file mode 100644 index 000000000..c255624e5 --- /dev/null +++ b/validator/src/main/java/dev/cel/validator/validators/AstDepthLimitValidator.java @@ -0,0 +1,69 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.validator.validators; + +import static com.google.common.base.Preconditions.checkArgument; + +import dev.cel.bundle.Cel; +import dev.cel.common.navigation.CelNavigableAst; +import dev.cel.validator.CelAstValidator; + +/** Enforces a compiled AST to stay below the configured depth limit. */ +public final class AstDepthLimitValidator implements CelAstValidator { + + // Protobuf imposes a default parse-depth limit of 100. We set it to half here because navigable + // expr does not include operands in the depth calculation. + // As an example, an expression 'x.y' has a depth of 2 in NavigableExpr, but the ParsedExpr has a + // depth of 4 as illustrated below: + // + // expr { + // id: 2 + // select_expr { + // operand { + // id: 1 + // ident_expr { + // name: "x" + // } + // } + // field: "y" + // } + // } + static final int DEFAULT_DEPTH_LIMIT = 50; + + public static final AstDepthLimitValidator DEFAULT = newInstance(DEFAULT_DEPTH_LIMIT); + private final int maxDepth; + + /** + * Constructs a new instance of {@link AstDepthLimitValidator} with the configured maxDepth as its + * limit. + */ + public static AstDepthLimitValidator newInstance(int maxDepth) { + checkArgument(maxDepth > 0); + return new AstDepthLimitValidator(maxDepth); + } + + @Override + public void validate(CelNavigableAst navigableAst, Cel cel, IssuesFactory issuesFactory) { + if (navigableAst.getRoot().height() >= maxDepth) { + issuesFactory.addError( + navigableAst.getRoot().id(), + String.format("AST's depth exceeds the configured limit: %s.", maxDepth)); + } + } + + private AstDepthLimitValidator(int maxDepth) { + this.maxDepth = maxDepth; + } +} diff --git a/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel b/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel index d049a3659..3362f14be 100644 --- a/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel +++ b/validator/src/main/java/dev/cel/validator/validators/BUILD.bazel @@ -67,6 +67,21 @@ java_library( ], ) +java_library( + name = "ast_depth_limit_validator", + srcs = [ + "AstDepthLimitValidator.java", + ], + tags = [ + ], + deps = [ + "//bundle:cel", + "//common/navigation", + "//validator:ast_validator", + "@maven//:com_google_guava_guava", + ], +) + java_library( name = "literal_validator", srcs = [ diff --git a/validator/src/test/java/dev/cel/validator/validators/AstDepthLimitValidatorTest.java b/validator/src/test/java/dev/cel/validator/validators/AstDepthLimitValidatorTest.java new file mode 100644 index 000000000..acc2544c7 --- /dev/null +++ b/validator/src/test/java/dev/cel/validator/validators/AstDepthLimitValidatorTest.java @@ -0,0 +1,112 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.validator.validators; + +import static com.google.common.truth.Truth.assertThat; +import static dev.cel.common.CelFunctionDecl.newFunctionDeclaration; +import static dev.cel.common.CelOverloadDecl.newGlobalOverload; +import static dev.cel.validator.validators.AstDepthLimitValidator.DEFAULT_DEPTH_LIMIT; +import static org.junit.Assert.assertThrows; + +import dev.cel.expr.CheckedExpr; +import com.google.protobuf.ByteString; +import com.google.protobuf.ExtensionRegistryLite; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.testing.junit.testparameterinjector.TestParameter; +import com.google.testing.junit.testparameterinjector.TestParameterInjector; +import dev.cel.bundle.Cel; +import dev.cel.bundle.CelFactory; +import dev.cel.common.CelAbstractSyntaxTree; +import dev.cel.common.CelIssue.Severity; +import dev.cel.common.CelProtoAbstractSyntaxTree; +import dev.cel.common.CelValidationResult; +import dev.cel.common.types.SimpleType; +import dev.cel.validator.CelValidator; +import dev.cel.validator.CelValidatorFactory; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(TestParameterInjector.class) +public class AstDepthLimitValidatorTest { + + private static final Cel CEL = + CelFactory.standardCelBuilder() + .addVar("x", SimpleType.DYN) + .addFunctionDeclarations( + newFunctionDeclaration( + "f", newGlobalOverload("f_int64", SimpleType.INT, SimpleType.INT))) + .build(); + + private static final CelValidator CEL_VALIDATOR = + CelValidatorFactory.standardCelValidatorBuilder(CEL) + .addAstValidators(AstDepthLimitValidator.DEFAULT) + .build(); + + private enum DefaultTestCase { + NESTED_SELECTS( + "x.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y"), + NESTED_CALCS( + "0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50"), + NESTED_FUNCS( + "f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(0)))))))))))))))))))))))))))))))))))))))))))))))))))"); + + private final String expression; + + DefaultTestCase(String expression) { + this.expression = expression; + } + } + + @Test + public void astExceedsDefaultDepthLimit_populatesErrors(@TestParameter DefaultTestCase testCase) + throws Exception { + CelAbstractSyntaxTree ast = CEL.compile(testCase.expression).getAst(); + + CelValidationResult result = CEL_VALIDATOR.validate(ast); + + assertThat(result.hasError()).isTrue(); + assertThat(result.getAllIssues()).hasSize(1); + assertThat(result.getAllIssues().get(0).getSeverity()).isEqualTo(Severity.ERROR); + assertThat(result.getAllIssues().get(0).toDisplayString(ast.getSource())) + .contains("AST's depth exceeds the configured limit: 50."); + assertThrows(InvalidProtocolBufferException.class, () -> verifyProtoAstRoundTrips(ast)); + } + + @Test + public void astIsUnderDepthLimit_noErrors() throws Exception { + StringBuilder sb = new StringBuilder().append("x"); + for (int i = 0; i < DEFAULT_DEPTH_LIMIT - 1; i++) { + sb.append(".y"); + } + // Depth level of 49 + CelAbstractSyntaxTree ast = CEL.compile(sb.toString()).getAst(); + + CelValidationResult result = CEL_VALIDATOR.validate(ast); + + assertThat(result.hasError()).isFalse(); + assertThat(result.getAllIssues()).isEmpty(); + verifyProtoAstRoundTrips(ast); + } + + private void verifyProtoAstRoundTrips(CelAbstractSyntaxTree ast) throws Exception { + CheckedExpr checkedExpr = CelProtoAbstractSyntaxTree.fromCelAst(ast).toCheckedExpr(); + ByteString serialized = checkedExpr.toByteString(); + CheckedExpr deserializedCheckedExpr = + CheckedExpr.parseFrom(serialized, ExtensionRegistryLite.getEmptyRegistry()); + if (!checkedExpr.equals(deserializedCheckedExpr)) { + throw new IllegalStateException("Expected checked expressions to round trip!"); + } + } +} diff --git a/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel b/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel index 1f8af4661..a04ee6d1e 100644 --- a/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel +++ b/validator/src/test/java/dev/cel/validator/validators/BUILD.bazel @@ -17,11 +17,13 @@ java_library( "//runtime", "//validator", "//validator:validator_builder", + "//validator/validators:ast_depth_limit_validator", "//validator/validators:duration", "//validator/validators:homogeneous_literal", "//validator/validators:regex", "//validator/validators:timestamp", "@@protobuf~//java/core", + "@cel_spec//proto/cel/expr:expr_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", diff --git a/validator/validators/BUILD.bazel b/validator/validators/BUILD.bazel index e4f9ea54b..a34f03049 100644 --- a/validator/validators/BUILD.bazel +++ b/validator/validators/BUILD.bazel @@ -22,3 +22,8 @@ java_library( name = "homogeneous_literal", exports = ["//validator/src/main/java/dev/cel/validator/validators:homogeneous_literal"], ) + +java_library( + name = "ast_depth_limit_validator", + exports = ["//validator/src/main/java/dev/cel/validator/validators:ast_depth_limit_validator"], +) From 80baca4ff2f4960401013e8831632ae8b3d7f2a3 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 15 Aug 2024 10:40:18 -0700 Subject: [PATCH 21/33] Enforce composed AST stays below the configured depth limit PiperOrigin-RevId: 663361547 --- .../src/main/java/dev/cel/policy/BUILD.bazel | 4 ++ .../cel/policy/CelPolicyCompilerBuilder.java | 7 +++ .../dev/cel/policy/CelPolicyCompilerImpl.java | 49 +++++++++++++++++-- .../cel/policy/CelPolicyCompilerImplTest.java | 36 ++++++++++++++ .../dev/cel/validator/CelAstValidator.java | 10 +++- 5 files changed, 101 insertions(+), 5 deletions(-) diff --git a/policy/src/main/java/dev/cel/policy/BUILD.bazel b/policy/src/main/java/dev/cel/policy/BUILD.bazel index ea3f4353c..bdb651d0d 100644 --- a/policy/src/main/java/dev/cel/policy/BUILD.bazel +++ b/policy/src/main/java/dev/cel/policy/BUILD.bazel @@ -257,6 +257,10 @@ java_library( "//optimizer", "//optimizer:optimization_exception", "//optimizer:optimizer_builder", + "//validator", + "//validator:ast_validator", + "//validator:validator_builder", + "//validator/validators:ast_depth_limit_validator", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyCompilerBuilder.java b/policy/src/main/java/dev/cel/policy/CelPolicyCompilerBuilder.java index 13bac2885..592a0120d 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyCompilerBuilder.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyCompilerBuilder.java @@ -31,6 +31,13 @@ public interface CelPolicyCompilerBuilder { @CanIgnoreReturnValue CelPolicyCompilerBuilder setIterationLimit(int iterationLimit); + /** + * Enforces the composed AST to stay below the configured depth limit. An exception is thrown if + * the depth exceeds the configured limit. Setting a negative value disables this check. + */ + @CanIgnoreReturnValue + CelPolicyCompilerBuilder setAstDepthLimit(int iterationLimit); + @CheckReturnValue CelPolicyCompiler build(); } diff --git a/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java b/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java index b7d1377b1..ca1be9f46 100644 --- a/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java +++ b/policy/src/main/java/dev/cel/policy/CelPolicyCompilerImpl.java @@ -25,6 +25,7 @@ import dev.cel.common.CelSource; import dev.cel.common.CelSourceLocation; import dev.cel.common.CelValidationException; +import dev.cel.common.CelValidationResult; import dev.cel.common.CelVarDecl; import dev.cel.common.ast.CelConstant; import dev.cel.common.ast.CelExpr; @@ -40,6 +41,10 @@ import dev.cel.policy.CelPolicy.Match; import dev.cel.policy.CelPolicy.Variable; import dev.cel.policy.RuleComposer.RuleCompositionException; +import dev.cel.validator.CelAstValidator; +import dev.cel.validator.CelValidator; +import dev.cel.validator.CelValidatorFactory; +import dev.cel.validator.validators.AstDepthLimitValidator; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -52,6 +57,7 @@ final class CelPolicyCompilerImpl implements CelPolicyCompiler { private final Cel cel; private final String variablesPrefix; private final int iterationLimit; + private final Optional astDepthValidator; @Override public CelCompiledRule compileRule(CelPolicy policy) throws CelPolicyValidationException { @@ -67,8 +73,9 @@ public CelCompiledRule compileRule(CelPolicy policy) throws CelPolicyValidationE @Override public CelAbstractSyntaxTree compose(CelPolicy policy, CelCompiledRule compiledRule) throws CelPolicyValidationException { + Cel cel = compiledRule.cel(); CelOptimizer optimizer = - CelOptimizerFactory.standardCelOptimizerBuilder(compiledRule.cel()) + CelOptimizerFactory.standardCelOptimizerBuilder(cel) .addAstOptimizers( RuleComposer.newInstance(compiledRule, variablesPrefix, iterationLimit)) .build(); @@ -105,9 +112,26 @@ public CelAbstractSyntaxTree compose(CelPolicy policy, CelCompiledRule compiledR throw new CelPolicyValidationException("Unexpected error while composing rules.", e); } + assertAstDepthIsSafe(ast, cel); + return ast; } + private void assertAstDepthIsSafe(CelAbstractSyntaxTree ast, Cel cel) + throws CelPolicyValidationException { + if (!astDepthValidator.isPresent()) { + return; + } + CelValidator celValidator = + CelValidatorFactory.standardCelValidatorBuilder(cel) + .addAstValidators(astDepthValidator.get()) + .build(); + CelValidationResult result = celValidator.validate(ast); + if (result.hasError()) { + throw new CelPolicyValidationException(result.getErrorString()); + } + } + private CelCompiledRule compileRuleImpl( CelPolicy.Rule rule, Cel ruleCel, CompilerContext compilerContext) { ImmutableList.Builder variableBuilder = ImmutableList.builder(); @@ -262,9 +286,11 @@ static final class Builder implements CelPolicyCompilerBuilder { private final Cel cel; private String variablesPrefix; private int iterationLimit; + private Optional astDepthLimitValidator; private Builder(Cel cel) { this.cel = cel; + this.astDepthLimitValidator = Optional.of(AstDepthLimitValidator.DEFAULT); } @Override @@ -281,9 +307,21 @@ public Builder setIterationLimit(int iterationLimit) { return this; } + @Override + @CanIgnoreReturnValue + public CelPolicyCompilerBuilder setAstDepthLimit(int astDepthLimit) { + if (astDepthLimit < 0) { + astDepthLimitValidator = Optional.empty(); + } else { + astDepthLimitValidator = Optional.of(AstDepthLimitValidator.newInstance(astDepthLimit)); + } + return this; + } + @Override public CelPolicyCompiler build() { - return new CelPolicyCompilerImpl(cel, this.variablesPrefix, this.iterationLimit); + return new CelPolicyCompilerImpl( + cel, this.variablesPrefix, this.iterationLimit, astDepthLimitValidator); } } @@ -293,9 +331,14 @@ static Builder newBuilder(Cel cel) { .setIterationLimit(DEFAULT_ITERATION_LIMIT); } - private CelPolicyCompilerImpl(Cel cel, String variablesPrefix, int iterationLimit) { + private CelPolicyCompilerImpl( + Cel cel, + String variablesPrefix, + int iterationLimit, + Optional astDepthValidator) { this.cel = checkNotNull(cel); this.variablesPrefix = checkNotNull(variablesPrefix); this.iterationLimit = iterationLimit; + this.astDepthValidator = astDepthValidator; } } diff --git a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java index 7d4bb85d1..bf435f90a 100644 --- a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java +++ b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java @@ -105,6 +105,42 @@ public void compileYamlPolicy_multilineContainsError_throws( assertThat(e).hasMessageThat().isEqualTo(testCase.expected); } + @Test + public void compileYamlPolicy_exceedsDefaultAstDepthLimit_throws() throws Exception { + String longExpr = + "0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50"; + String policyContent = + String.format( + "name: deeply_nested_ast\n" + "rule:\n" + " match:\n" + " - output: %s", longExpr); + CelPolicy policy = POLICY_PARSER.parse(policyContent); + + CelPolicyValidationException e = + assertThrows( + CelPolicyValidationException.class, + () -> CelPolicyCompilerFactory.newPolicyCompiler(newCel()).build().compile(policy)); + + assertThat(e) + .hasMessageThat() + .isEqualTo("ERROR: :-1:0: AST's depth exceeds the configured limit: 50."); + } + + @Test + public void compileYamlPolicy_astDepthLimitCheckDisabled_doesNotThrow() throws Exception { + String longExpr = + "0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50"; + String policyContent = + String.format( + "name: deeply_nested_ast\n" + "rule:\n" + " match:\n" + " - output: %s", longExpr); + CelPolicy policy = POLICY_PARSER.parse(policyContent); + + CelAbstractSyntaxTree ast = + CelPolicyCompilerFactory.newPolicyCompiler(newCel()) + .setAstDepthLimit(-1) + .build() + .compile(policy); + assertThat(ast).isNotNull(); + } + @Test @SuppressWarnings("unchecked") public void evaluateYamlPolicy_withCanonicalTestData( diff --git a/validator/src/main/java/dev/cel/validator/CelAstValidator.java b/validator/src/main/java/dev/cel/validator/CelAstValidator.java index ca316019a..d3b046686 100644 --- a/validator/src/main/java/dev/cel/validator/CelAstValidator.java +++ b/validator/src/main/java/dev/cel/validator/CelAstValidator.java @@ -19,7 +19,9 @@ import dev.cel.common.CelIssue; import dev.cel.common.CelIssue.Severity; import dev.cel.common.CelSource; +import dev.cel.common.CelSourceLocation; import dev.cel.common.navigation.CelNavigableAst; +import java.util.Optional; /** Public interface for performing a single, custom validation on an AST. */ public interface CelAstValidator { @@ -53,12 +55,16 @@ public void addInfo(long exprId, String message) { private void add(long exprId, String message, Severity severity) { CelSource source = navigableAst.getAst().getSource(); - int position = source.getPositionsMap().get(exprId); + int position = Optional.ofNullable(source.getPositionsMap().get(exprId)).orElse(-1); + CelSourceLocation sourceLocation = CelSourceLocation.NONE; + if (position >= 0) { + sourceLocation = source.getOffsetLocation(position).get(); + } issuesBuilder.add( CelIssue.newBuilder() .setSeverity(severity) .setMessage(message) - .setSourceLocation(source.getOffsetLocation(position).get()) + .setSourceLocation(sourceLocation) .build()); } From c1a05d69a72acec9f5c75bcd02f35ecf90593729 Mon Sep 17 00:00:00 2001 From: Justin King Date: Fri, 16 Aug 2024 10:03:58 -0700 Subject: [PATCH 22/33] Add a test case showing adjacent comprehensions PiperOrigin-RevId: 663765762 --- .../SubexpressionOptimizerBaselineTest.java | 2 + ...old_before_subexpression_unparsed.baseline | 16 ++ ...ion_ast_block_common_subexpr_only.baseline | 190 ++++++++++++++++ ...ssion_ast_block_recursion_depth_1.baseline | 208 +++++++++++++++++ ...ssion_ast_block_recursion_depth_2.baseline | 214 ++++++++++++++++++ ...ssion_ast_block_recursion_depth_3.baseline | 202 +++++++++++++++++ ...ssion_ast_block_recursion_depth_4.baseline | 196 ++++++++++++++++ ...ssion_ast_block_recursion_depth_5.baseline | 196 ++++++++++++++++ ...ssion_ast_block_recursion_depth_6.baseline | 196 ++++++++++++++++ ...ssion_ast_block_recursion_depth_7.baseline | 196 ++++++++++++++++ ...ssion_ast_block_recursion_depth_8.baseline | 190 ++++++++++++++++ ...ssion_ast_block_recursion_depth_9.baseline | 190 ++++++++++++++++ .../subexpression_ast_cascaded_binds.baseline | 203 +++++++++++++++++ .../resources/subexpression_unparsed.baseline | 16 ++ 14 files changed, 2215 insertions(+) diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index f5a1c4086..2cb3df813 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -461,6 +461,8 @@ private enum CseTestCase { + " 1)"), NESTED_MACROS("[1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [[2, 3, 4], [2, 3, 4], [2, 3, 4]]"), NESTED_MACROS_2("[1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]]"), + ADJACENT_NESTED_MACROS( + "[1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1))"), INCLUSION_LIST("1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3]"), INCLUSION_MAP("2 in {'a': 1, 2: {true: false}, 3: {true: false}}"), MACRO_ITER_VAR_NOT_REFERENCED( diff --git a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline index b18460018..897b4d775 100644 --- a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline @@ -350,6 +350,22 @@ Result: true [BLOCK_RECURSION_DEPTH_8]: true [BLOCK_RECURSION_DEPTH_9]: true +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +Result: true +[CASCADED_BINDS]: true +[BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_RECURSION_DEPTH_1]: true +[BLOCK_RECURSION_DEPTH_2]: true +[BLOCK_RECURSION_DEPTH_3]: true +[BLOCK_RECURSION_DEPTH_4]: true +[BLOCK_RECURSION_DEPTH_5]: true +[BLOCK_RECURSION_DEPTH_6]: true +[BLOCK_RECURSION_DEPTH_7]: true +[BLOCK_RECURSION_DEPTH_8]: true +[BLOCK_RECURSION_DEPTH_9]: true + Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline index c1ad64871..d2267c0d8 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline @@ -2151,6 +2151,196 @@ CALL [31] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + } + } + CALL [7] { + function: _==_ + args: { + COMPREHENSION [8] { + iter_var: @c:1 + iter_range: { + IDENT [9] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [10] { + elements: { + } + } + } + loop_condition: { + CONSTANT [11] { value: true } + } + loop_step: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @x:1 + } + LIST [14] { + elements: { + COMPREHENSION [15] { + iter_var: @c:0 + iter_range: { + IDENT [16] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [17] { + elements: { + } + } + } + loop_condition: { + CONSTANT [18] { value: true } + } + loop_step: { + CALL [19] { + function: _+_ + args: { + IDENT [20] { + name: @x:0 + } + LIST [21] { + elements: { + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @c:0 + } + CONSTANT [24] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [25] { + name: @x:0 + } + } + } + } + } + } + } + } + result: { + IDENT [26] { + name: @x:1 + } + } + } + COMPREHENSION [27] { + iter_var: @c:3 + iter_range: { + IDENT [28] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [29] { + elements: { + } + } + } + loop_condition: { + CONSTANT [30] { value: true } + } + loop_step: { + CALL [31] { + function: _+_ + args: { + IDENT [32] { + name: @x:3 + } + LIST [33] { + elements: { + COMPREHENSION [34] { + iter_var: @c:2 + iter_range: { + IDENT [35] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [36] { + elements: { + } + } + } + loop_condition: { + CONSTANT [37] { value: true } + } + loop_step: { + CALL [38] { + function: _+_ + args: { + IDENT [39] { + name: @x:2 + } + LIST [40] { + elements: { + CALL [41] { + function: _+_ + args: { + IDENT [42] { + name: @c:2 + } + CONSTANT [43] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [44] { + name: @x:2 + } + } + } + } + } + } + } + } + result: { + IDENT [45] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline index 1b081c43c..bcfc70fb1 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline @@ -2592,6 +2592,214 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + CALL [7] { + function: _+_ + args: { + IDENT [8] { + name: @c:0 + } + CONSTANT [9] { value: 1 } + } + } + LIST [10] { + elements: { + IDENT [11] { + name: @index1 + } + } + } + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @x:0 + } + IDENT [14] { + name: @index2 + } + } + } + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @c:2 + } + CONSTANT [17] { value: 1 } + } + } + LIST [18] { + elements: { + IDENT [19] { + name: @index4 + } + } + } + CALL [20] { + function: _+_ + args: { + IDENT [21] { + name: @x:2 + } + IDENT [22] { + name: @index5 + } + } + } + } + } + CALL [23] { + function: _==_ + args: { + COMPREHENSION [24] { + iter_var: @c:1 + iter_range: { + IDENT [25] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [26] { + elements: { + } + } + } + loop_condition: { + CONSTANT [27] { value: true } + } + loop_step: { + CALL [28] { + function: _+_ + args: { + IDENT [29] { + name: @x:1 + } + LIST [30] { + elements: { + COMPREHENSION [31] { + iter_var: @c:0 + iter_range: { + IDENT [32] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [33] { + elements: { + } + } + } + loop_condition: { + CONSTANT [34] { value: true } + } + loop_step: { + IDENT [35] { + name: @index3 + } + } + result: { + IDENT [36] { + name: @x:0 + } + } + } + } + } + } + } + } + result: { + IDENT [37] { + name: @x:1 + } + } + } + COMPREHENSION [38] { + iter_var: @c:3 + iter_range: { + IDENT [39] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [40] { + elements: { + } + } + } + loop_condition: { + CONSTANT [41] { value: true } + } + loop_step: { + CALL [42] { + function: _+_ + args: { + IDENT [43] { + name: @x:3 + } + LIST [44] { + elements: { + COMPREHENSION [45] { + iter_var: @c:2 + iter_range: { + IDENT [46] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [47] { + elements: { + } + } + } + loop_condition: { + CONSTANT [48] { value: true } + } + loop_step: { + IDENT [49] { + name: @index6 + } + } + result: { + IDENT [50] { + name: @x:2 + } + } + } + } + } + } + } + } + result: { + IDENT [51] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline index 1d3045ff6..7a46177d8 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline @@ -2368,6 +2368,220 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + LIST [7] { + elements: { + CALL [8] { + function: _+_ + args: { + IDENT [9] { + name: @c:0 + } + CONSTANT [10] { value: 1 } + } + } + } + } + COMPREHENSION [11] { + iter_var: @c:0 + iter_range: { + IDENT [12] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [13] { + elements: { + } + } + } + loop_condition: { + CONSTANT [14] { value: true } + } + loop_step: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @x:0 + } + IDENT [17] { + name: @index1 + } + } + } + } + result: { + IDENT [18] { + name: @x:0 + } + } + } + CALL [19] { + function: _+_ + args: { + IDENT [20] { + name: @x:1 + } + LIST [21] { + elements: { + IDENT [22] { + name: @index2 + } + } + } + } + } + COMPREHENSION [23] { + iter_var: @c:1 + iter_range: { + IDENT [24] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [25] { + elements: { + } + } + } + loop_condition: { + CONSTANT [26] { value: true } + } + loop_step: { + IDENT [27] { + name: @index3 + } + } + result: { + IDENT [28] { + name: @x:1 + } + } + } + LIST [29] { + elements: { + CALL [30] { + function: _+_ + args: { + IDENT [31] { + name: @c:2 + } + CONSTANT [32] { value: 1 } + } + } + } + } + COMPREHENSION [33] { + iter_var: @c:2 + iter_range: { + IDENT [34] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [35] { + elements: { + } + } + } + loop_condition: { + CONSTANT [36] { value: true } + } + loop_step: { + CALL [37] { + function: _+_ + args: { + IDENT [38] { + name: @x:2 + } + IDENT [39] { + name: @index5 + } + } + } + } + result: { + IDENT [40] { + name: @x:2 + } + } + } + CALL [41] { + function: _+_ + args: { + IDENT [42] { + name: @x:3 + } + LIST [43] { + elements: { + IDENT [44] { + name: @index6 + } + } + } + } + } + COMPREHENSION [45] { + iter_var: @c:3 + iter_range: { + IDENT [46] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [47] { + elements: { + } + } + } + loop_condition: { + CONSTANT [48] { value: true } + } + loop_step: { + IDENT [49] { + name: @index7 + } + } + result: { + IDENT [50] { + name: @x:3 + } + } + } + } + } + CALL [51] { + function: _==_ + args: { + IDENT [52] { + name: @index4 + } + IDENT [53] { + name: @index8 + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline index f9c1f2a42..6ecc6d04a 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline @@ -2303,6 +2303,208 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + CALL [7] { + function: _+_ + args: { + IDENT [8] { + name: @x:0 + } + LIST [9] { + elements: { + CALL [10] { + function: _+_ + args: { + IDENT [11] { + name: @c:0 + } + CONSTANT [12] { value: 1 } + } + } + } + } + } + } + LIST [13] { + elements: { + COMPREHENSION [14] { + iter_var: @c:0 + iter_range: { + IDENT [15] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [16] { + elements: { + } + } + } + loop_condition: { + CONSTANT [17] { value: true } + } + loop_step: { + IDENT [18] { + name: @index1 + } + } + result: { + IDENT [19] { + name: @x:0 + } + } + } + } + } + CALL [20] { + function: _+_ + args: { + IDENT [21] { + name: @x:2 + } + LIST [22] { + elements: { + CALL [23] { + function: _+_ + args: { + IDENT [24] { + name: @c:2 + } + CONSTANT [25] { value: 1 } + } + } + } + } + } + } + LIST [26] { + elements: { + COMPREHENSION [27] { + iter_var: @c:2 + iter_range: { + IDENT [28] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [29] { + elements: { + } + } + } + loop_condition: { + CONSTANT [30] { value: true } + } + loop_step: { + IDENT [31] { + name: @index3 + } + } + result: { + IDENT [32] { + name: @x:2 + } + } + } + } + } + } + } + CALL [33] { + function: _==_ + args: { + COMPREHENSION [34] { + iter_var: @c:1 + iter_range: { + IDENT [35] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [36] { + elements: { + } + } + } + loop_condition: { + CONSTANT [37] { value: true } + } + loop_step: { + CALL [38] { + function: _+_ + args: { + IDENT [39] { + name: @x:1 + } + IDENT [40] { + name: @index2 + } + } + } + } + result: { + IDENT [41] { + name: @x:1 + } + } + } + COMPREHENSION [42] { + iter_var: @c:3 + iter_range: { + IDENT [43] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [44] { + elements: { + } + } + } + loop_condition: { + CONSTANT [45] { value: true } + } + loop_step: { + CALL [46] { + function: _+_ + args: { + IDENT [47] { + name: @x:3 + } + IDENT [48] { + name: @index4 + } + } + } + } + result: { + IDENT [49] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline index a640f81da..0bfb05eaf 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline @@ -2252,6 +2252,202 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + COMPREHENSION [7] { + iter_var: @c:0 + iter_range: { + IDENT [8] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [9] { + elements: { + } + } + } + loop_condition: { + CONSTANT [10] { value: true } + } + loop_step: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @x:0 + } + LIST [13] { + elements: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @c:0 + } + CONSTANT [16] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [17] { + name: @x:0 + } + } + } + COMPREHENSION [18] { + iter_var: @c:2 + iter_range: { + IDENT [19] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [20] { + elements: { + } + } + } + loop_condition: { + CONSTANT [21] { value: true } + } + loop_step: { + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @x:2 + } + LIST [24] { + elements: { + CALL [25] { + function: _+_ + args: { + IDENT [26] { + name: @c:2 + } + CONSTANT [27] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [28] { + name: @x:2 + } + } + } + } + } + CALL [29] { + function: _==_ + args: { + COMPREHENSION [30] { + iter_var: @c:1 + iter_range: { + IDENT [31] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [32] { + elements: { + } + } + } + loop_condition: { + CONSTANT [33] { value: true } + } + loop_step: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @x:1 + } + LIST [36] { + elements: { + IDENT [37] { + name: @index1 + } + } + } + } + } + } + result: { + IDENT [38] { + name: @x:1 + } + } + } + COMPREHENSION [39] { + iter_var: @c:3 + iter_range: { + IDENT [40] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [41] { + elements: { + } + } + } + loop_condition: { + CONSTANT [42] { value: true } + } + loop_step: { + CALL [43] { + function: _+_ + args: { + IDENT [44] { + name: @x:3 + } + LIST [45] { + elements: { + IDENT [46] { + name: @index2 + } + } + } + } + } + } + result: { + IDENT [47] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline index ba9b61292..ed7daab1e 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline @@ -2222,6 +2222,202 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + LIST [7] { + elements: { + COMPREHENSION [8] { + iter_var: @c:0 + iter_range: { + IDENT [9] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [10] { + elements: { + } + } + } + loop_condition: { + CONSTANT [11] { value: true } + } + loop_step: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @x:0 + } + LIST [14] { + elements: { + CALL [15] { + function: _+_ + args: { + IDENT [16] { + name: @c:0 + } + CONSTANT [17] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [18] { + name: @x:0 + } + } + } + } + } + LIST [19] { + elements: { + COMPREHENSION [20] { + iter_var: @c:2 + iter_range: { + IDENT [21] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [22] { + elements: { + } + } + } + loop_condition: { + CONSTANT [23] { value: true } + } + loop_step: { + CALL [24] { + function: _+_ + args: { + IDENT [25] { + name: @x:2 + } + LIST [26] { + elements: { + CALL [27] { + function: _+_ + args: { + IDENT [28] { + name: @c:2 + } + CONSTANT [29] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [30] { + name: @x:2 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + COMPREHENSION [32] { + iter_var: @c:1 + iter_range: { + IDENT [33] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [34] { + elements: { + } + } + } + loop_condition: { + CONSTANT [35] { value: true } + } + loop_step: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @x:1 + } + IDENT [38] { + name: @index1 + } + } + } + } + result: { + IDENT [39] { + name: @x:1 + } + } + } + COMPREHENSION [40] { + iter_var: @c:3 + iter_range: { + IDENT [41] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [42] { + elements: { + } + } + } + loop_condition: { + CONSTANT [43] { value: true } + } + loop_step: { + CALL [44] { + function: _+_ + args: { + IDENT [45] { + name: @x:3 + } + IDENT [46] { + name: @index2 + } + } + } + } + result: { + IDENT [47] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline index b68e6eaf1..0172a0726 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline @@ -2207,6 +2207,202 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + CALL [7] { + function: _+_ + args: { + IDENT [8] { + name: @x:1 + } + LIST [9] { + elements: { + COMPREHENSION [10] { + iter_var: @c:0 + iter_range: { + IDENT [11] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [12] { + elements: { + } + } + } + loop_condition: { + CONSTANT [13] { value: true } + } + loop_step: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @x:0 + } + LIST [16] { + elements: { + CALL [17] { + function: _+_ + args: { + IDENT [18] { + name: @c:0 + } + CONSTANT [19] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [20] { + name: @x:0 + } + } + } + } + } + } + } + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @x:3 + } + LIST [23] { + elements: { + COMPREHENSION [24] { + iter_var: @c:2 + iter_range: { + IDENT [25] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [26] { + elements: { + } + } + } + loop_condition: { + CONSTANT [27] { value: true } + } + loop_step: { + CALL [28] { + function: _+_ + args: { + IDENT [29] { + name: @x:2 + } + LIST [30] { + elements: { + CALL [31] { + function: _+_ + args: { + IDENT [32] { + name: @c:2 + } + CONSTANT [33] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [34] { + name: @x:2 + } + } + } + } + } + } + } + } + } + CALL [35] { + function: _==_ + args: { + COMPREHENSION [36] { + iter_var: @c:1 + iter_range: { + IDENT [37] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [38] { + elements: { + } + } + } + loop_condition: { + CONSTANT [39] { value: true } + } + loop_step: { + IDENT [40] { + name: @index1 + } + } + result: { + IDENT [41] { + name: @x:1 + } + } + } + COMPREHENSION [42] { + iter_var: @c:3 + iter_range: { + IDENT [43] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [44] { + elements: { + } + } + } + loop_condition: { + CONSTANT [45] { value: true } + } + loop_step: { + IDENT [46] { + name: @index2 + } + } + result: { + IDENT [47] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline index 410c1ff1a..5fa185080 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline @@ -2198,6 +2198,202 @@ CALL [1] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + COMPREHENSION [7] { + iter_var: @c:1 + iter_range: { + IDENT [8] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [9] { + elements: { + } + } + } + loop_condition: { + CONSTANT [10] { value: true } + } + loop_step: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @x:1 + } + LIST [13] { + elements: { + COMPREHENSION [14] { + iter_var: @c:0 + iter_range: { + IDENT [15] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [16] { + elements: { + } + } + } + loop_condition: { + CONSTANT [17] { value: true } + } + loop_step: { + CALL [18] { + function: _+_ + args: { + IDENT [19] { + name: @x:0 + } + LIST [20] { + elements: { + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @c:0 + } + CONSTANT [23] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [24] { + name: @x:0 + } + } + } + } + } + } + } + } + result: { + IDENT [25] { + name: @x:1 + } + } + } + COMPREHENSION [26] { + iter_var: @c:3 + iter_range: { + IDENT [27] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [28] { + elements: { + } + } + } + loop_condition: { + CONSTANT [29] { value: true } + } + loop_step: { + CALL [30] { + function: _+_ + args: { + IDENT [31] { + name: @x:3 + } + LIST [32] { + elements: { + COMPREHENSION [33] { + iter_var: @c:2 + iter_range: { + IDENT [34] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [35] { + elements: { + } + } + } + loop_condition: { + CONSTANT [36] { value: true } + } + loop_step: { + CALL [37] { + function: _+_ + args: { + IDENT [38] { + name: @x:2 + } + LIST [39] { + elements: { + CALL [40] { + function: _+_ + args: { + IDENT [41] { + name: @c:2 + } + CONSTANT [42] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [43] { + name: @x:2 + } + } + } + } + } + } + } + } + result: { + IDENT [44] { + name: @x:3 + } + } + } + } + } + CALL [45] { + function: _==_ + args: { + IDENT [46] { + name: @index1 + } + IDENT [47] { + name: @index2 + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline index d8c949600..9da40d283 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline @@ -2180,6 +2180,196 @@ CALL [31] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + } + } + CALL [7] { + function: _==_ + args: { + COMPREHENSION [8] { + iter_var: @c:1 + iter_range: { + IDENT [9] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [10] { + elements: { + } + } + } + loop_condition: { + CONSTANT [11] { value: true } + } + loop_step: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @x:1 + } + LIST [14] { + elements: { + COMPREHENSION [15] { + iter_var: @c:0 + iter_range: { + IDENT [16] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [17] { + elements: { + } + } + } + loop_condition: { + CONSTANT [18] { value: true } + } + loop_step: { + CALL [19] { + function: _+_ + args: { + IDENT [20] { + name: @x:0 + } + LIST [21] { + elements: { + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @c:0 + } + CONSTANT [24] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [25] { + name: @x:0 + } + } + } + } + } + } + } + } + result: { + IDENT [26] { + name: @x:1 + } + } + } + COMPREHENSION [27] { + iter_var: @c:3 + iter_range: { + IDENT [28] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [29] { + elements: { + } + } + } + loop_condition: { + CONSTANT [30] { value: true } + } + loop_step: { + CALL [31] { + function: _+_ + args: { + IDENT [32] { + name: @x:3 + } + LIST [33] { + elements: { + COMPREHENSION [34] { + iter_var: @c:2 + iter_range: { + IDENT [35] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [36] { + elements: { + } + } + } + loop_condition: { + CONSTANT [37] { value: true } + } + loop_step: { + CALL [38] { + function: _+_ + args: { + IDENT [39] { + name: @x:2 + } + LIST [40] { + elements: { + CALL [41] { + function: _+_ + args: { + IDENT [42] { + name: @c:2 + } + CONSTANT [43] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [44] { + name: @x:2 + } + } + } + } + } + } + } + } + result: { + IDENT [45] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline index b9bccc56c..025cd4769 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline @@ -2165,6 +2165,196 @@ CALL [31] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + } + } + CALL [7] { + function: _==_ + args: { + COMPREHENSION [8] { + iter_var: @c:1 + iter_range: { + IDENT [9] { + name: @index0 + } + } + accu_var: @x:1 + accu_init: { + LIST [10] { + elements: { + } + } + } + loop_condition: { + CONSTANT [11] { value: true } + } + loop_step: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @x:1 + } + LIST [14] { + elements: { + COMPREHENSION [15] { + iter_var: @c:0 + iter_range: { + IDENT [16] { + name: @index0 + } + } + accu_var: @x:0 + accu_init: { + LIST [17] { + elements: { + } + } + } + loop_condition: { + CONSTANT [18] { value: true } + } + loop_step: { + CALL [19] { + function: _+_ + args: { + IDENT [20] { + name: @x:0 + } + LIST [21] { + elements: { + CALL [22] { + function: _+_ + args: { + IDENT [23] { + name: @c:0 + } + CONSTANT [24] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [25] { + name: @x:0 + } + } + } + } + } + } + } + } + result: { + IDENT [26] { + name: @x:1 + } + } + } + COMPREHENSION [27] { + iter_var: @c:3 + iter_range: { + IDENT [28] { + name: @index0 + } + } + accu_var: @x:3 + accu_init: { + LIST [29] { + elements: { + } + } + } + loop_condition: { + CONSTANT [30] { value: true } + } + loop_step: { + CALL [31] { + function: _+_ + args: { + IDENT [32] { + name: @x:3 + } + LIST [33] { + elements: { + COMPREHENSION [34] { + iter_var: @c:2 + iter_range: { + IDENT [35] { + name: @index0 + } + } + accu_var: @x:2 + accu_init: { + LIST [36] { + elements: { + } + } + } + loop_condition: { + CONSTANT [37] { value: true } + } + loop_step: { + CALL [38] { + function: _+_ + args: { + IDENT [39] { + name: @x:2 + } + LIST [40] { + elements: { + CALL [41] { + function: _+_ + args: { + IDENT [42] { + name: @c:2 + } + CONSTANT [43] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [44] { + name: @x:2 + } + } + } + } + } + } + } + } + result: { + IDENT [45] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline index 5d09067b9..14ec4f9e6 100644 --- a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline +++ b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline @@ -2697,6 +2697,209 @@ CALL [31] { } } } +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +COMPREHENSION [1] { + iter_var: #unused + iter_range: { + LIST [2] { + elements: { + } + } + } + accu_var: @r0 + accu_init: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + } + loop_condition: { + CONSTANT [7] { value: false } + } + loop_step: { + IDENT [8] { + name: @r0 + } + } + result: { + CALL [9] { + function: _==_ + args: { + COMPREHENSION [10] { + iter_var: @c:1 + iter_range: { + IDENT [11] { + name: @r0 + } + } + accu_var: @x:1 + accu_init: { + LIST [12] { + elements: { + } + } + } + loop_condition: { + CONSTANT [13] { value: true } + } + loop_step: { + CALL [14] { + function: _+_ + args: { + IDENT [15] { + name: @x:1 + } + LIST [16] { + elements: { + COMPREHENSION [17] { + iter_var: @c:0 + iter_range: { + IDENT [18] { + name: @r0 + } + } + accu_var: @x:0 + accu_init: { + LIST [19] { + elements: { + } + } + } + loop_condition: { + CONSTANT [20] { value: true } + } + loop_step: { + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @x:0 + } + LIST [23] { + elements: { + CALL [24] { + function: _+_ + args: { + IDENT [25] { + name: @c:0 + } + CONSTANT [26] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [27] { + name: @x:0 + } + } + } + } + } + } + } + } + result: { + IDENT [28] { + name: @x:1 + } + } + } + COMPREHENSION [29] { + iter_var: @c:3 + iter_range: { + IDENT [30] { + name: @r0 + } + } + accu_var: @x:3 + accu_init: { + LIST [31] { + elements: { + } + } + } + loop_condition: { + CONSTANT [32] { value: true } + } + loop_step: { + CALL [33] { + function: _+_ + args: { + IDENT [34] { + name: @x:3 + } + LIST [35] { + elements: { + COMPREHENSION [36] { + iter_var: @c:2 + iter_range: { + IDENT [37] { + name: @r0 + } + } + accu_var: @x:2 + accu_init: { + LIST [38] { + elements: { + } + } + } + loop_condition: { + CONSTANT [39] { value: true } + } + loop_step: { + CALL [40] { + function: _+_ + args: { + IDENT [41] { + name: @x:2 + } + LIST [42] { + elements: { + CALL [43] { + function: _+_ + args: { + IDENT [44] { + name: @c:2 + } + CONSTANT [45] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [46] { + name: @x:2 + } + } + } + } + } + } + } + } + result: { + IDENT [47] { + name: @x:3 + } + } + } + } + } + } +} Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> diff --git a/optimizer/src/test/resources/subexpression_unparsed.baseline b/optimizer/src/test/resources/subexpression_unparsed.baseline index 831290039..9675f3b3a 100644 --- a/optimizer/src/test/resources/subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/subexpression_unparsed.baseline @@ -350,6 +350,22 @@ Result: true [BLOCK_RECURSION_DEPTH_8]: [1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1)) == [[1], [2]] [BLOCK_RECURSION_DEPTH_9]: [1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1)) == [[1], [2]] +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +Result: true +[CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@c:1, @r0.map(@c:0, @c:0 + 1)) == @r0.map(@c:3, @r0.map(@c:2, @c:2 + 1))) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], @c:0 + 1, [@index1], @x:0 + @index2, @c:2 + 1, [@index4], @x:2 + @index5], @index0.map(@c:1, @index0.map(@c:0, @index1)) == @index0.map(@c:3, @index0.map(@c:2, @index4))) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3], [@c:0 + 1], @index0.map(@c:0, @c:0 + 1), @x:1 + [@index2], @index0.map(@c:1, @index2), [@c:2 + 1], @index0.map(@c:2, @c:2 + 1), @x:3 + [@index6], @index0.map(@c:3, @index6)], @index4 == @index8) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3], @x:0 + [@c:0 + 1], [@index0.map(@c:0, @c:0 + 1)], @x:2 + [@c:2 + 1], [@index0.map(@c:2, @c:2 + 1)]], @index0.map(@c:1) == @index0.map(@c:3)) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3], @index0.map(@c:0, @c:0 + 1), @index0.map(@c:2, @c:2 + 1)], @index0.map(@c:1, @index1) == @index0.map(@c:3, @index2)) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1, 2, 3], [@index0.map(@c:0, @c:0 + 1)], [@index0.map(@c:2, @c:2 + 1)]], @index0.map(@c:1) == @index0.map(@c:3)) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1, 2, 3], @x:1 + [@index0.map(@c:0, @c:0 + 1)], @x:3 + [@index0.map(@c:2, @c:2 + 1)]], @index0.map(@c:1) == @index0.map(@c:3)) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2, 3], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)), @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))], @index1 == @index2) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1, 2, 3]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1, 2, 3]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))) + Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] =====> From c3c493ab76dc44305cecb0e2fd2aa062915aa906 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Mon, 19 Aug 2024 14:02:31 -0700 Subject: [PATCH 23/33] Improve CSE for comprehensions by taking into their nesting level and types into account PiperOrigin-RevId: 664968878 --- .../java/dev/cel/optimizer/AstMutator.java | 89 +- .../optimizers/SubexpressionOptimizer.java | 14 +- .../dev/cel/optimizer/AstMutatorTest.java | 93 +- ...old_before_subexpression_unparsed.baseline | 22 +- .../large_expressions_bind_cascaded.baseline | 2 +- ..._expressions_block_common_subexpr.baseline | 2 +- ...pressions_block_recursion_depth_1.baseline | 2 +- ...pressions_block_recursion_depth_2.baseline | 2 +- ...pressions_block_recursion_depth_3.baseline | 2 +- ...ion_ast_block_common_subexpr_only.baseline | 1130 ++++++---------- ...ssion_ast_block_recursion_depth_1.baseline | 799 +++++------- ...ssion_ast_block_recursion_depth_2.baseline | 897 +++++-------- ...ssion_ast_block_recursion_depth_3.baseline | 1009 +++++---------- ...ssion_ast_block_recursion_depth_4.baseline | 1000 +++++--------- ...ssion_ast_block_recursion_depth_5.baseline | 1089 +++++----------- ...ssion_ast_block_recursion_depth_6.baseline | 1132 ++++++---------- ...ssion_ast_block_recursion_depth_7.baseline | 1145 ++++++---------- ...ssion_ast_block_recursion_depth_8.baseline | 1152 ++++++----------- ...ssion_ast_block_recursion_depth_9.baseline | 1149 ++++++---------- .../subexpression_ast_cascaded_binds.baseline | 274 ++-- .../resources/subexpression_unparsed.baseline | 198 +-- 21 files changed, 4029 insertions(+), 7173 deletions(-) diff --git a/optimizer/src/main/java/dev/cel/optimizer/AstMutator.java b/optimizer/src/main/java/dev/cel/optimizer/AstMutator.java index aa90f1528..a731ac21e 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/AstMutator.java +++ b/optimizer/src/main/java/dev/cel/optimizer/AstMutator.java @@ -21,7 +21,9 @@ import com.google.auto.value.AutoValue; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Table; import com.google.errorprone.annotations.Immutable; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelMutableAst; @@ -270,17 +272,22 @@ public CelMutableAst renumberIdsConsecutively(CelMutableAst mutableAst) { * @param ast AST containing type-checked references * @param newIterVarPrefix Prefix to use for new iteration variable identifier name. For example, * providing @c will produce @c0:0, @c0:1, @c1:0, @c2:0... as new names. - * @param newResultPrefix Prefix to use for new comprehensin result identifier names. + * @param newAccuVarPrefix Prefix to use for new accumulation variable identifier name. + * @param incrementSerially If true, indices for the mangled variables are incremented serially + * per occurrence regardless of their nesting level or its types. */ public MangledComprehensionAst mangleComprehensionIdentifierNames( - CelMutableAst ast, String newIterVarPrefix, String newResultPrefix) { + CelMutableAst ast, + String newIterVarPrefix, + String newAccuVarPrefix, + boolean incrementSerially) { CelNavigableMutableAst navigableMutableAst = CelNavigableMutableAst.fromAst(ast); Predicate comprehensionIdentifierPredicate = x -> true; comprehensionIdentifierPredicate = comprehensionIdentifierPredicate .and(node -> node.getKind().equals(Kind.COMPREHENSION)) .and(node -> !node.expr().comprehension().iterVar().startsWith(newIterVarPrefix)) - .and(node -> !node.expr().comprehension().accuVar().startsWith(newResultPrefix)); + .and(node -> !node.expr().comprehension().accuVar().startsWith(newAccuVarPrefix)); LinkedHashMap comprehensionsToMangle = navigableMutableAst @@ -352,18 +359,43 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames( // The map that we'll eventually return to the caller. HashMap mangledIdentNamesToType = new HashMap<>(); + // Intermediary table used for the purposes of generating a unique mangled variable name. + Table comprehensionLevelToType = + HashBasedTable.create(); CelMutableExpr mutatedComprehensionExpr = navigableMutableAst.getAst().expr(); CelMutableSource newSource = navigableMutableAst.getAst().source(); int iterCount = 0; for (Entry comprehensionEntry : comprehensionsToMangle.entrySet()) { - String mangledIterVarName = newIterVarPrefix + ":" + iterCount; - String mangledResultName = newResultPrefix + ":" + iterCount; - MangledComprehensionName mangledComprehensionName = - MangledComprehensionName.of(mangledIterVarName, mangledResultName); - mangledIdentNamesToType.put(mangledComprehensionName, comprehensionEntry.getValue()); + CelNavigableMutableExpr comprehensionNode = comprehensionEntry.getKey(); + MangledComprehensionType comprehensionEntryType = comprehensionEntry.getValue(); + + CelMutableExpr comprehensionExpr = comprehensionNode.expr(); + MangledComprehensionName mangledComprehensionName; + if (incrementSerially) { + // In case of applying CSE via cascaded cel.binds, not only is mangling based on level/types + // meaningless (because all comprehensions are nested anyways, thus all indices would be + // uinque), + // it can lead to an erroneous result due to extracting a common subexpr with accu_var at + // the wrong scope. + // Example: "[1].exists(k, k > 1) && [2].exists(l, l > 1). The loop step for both branches + // are identical, but shouldn't be extracted. + String mangledIterVarName = newIterVarPrefix + ":" + iterCount; + String mangledResultName = newAccuVarPrefix + ":" + iterCount; + mangledComprehensionName = + MangledComprehensionName.of(mangledIterVarName, mangledResultName); + mangledIdentNamesToType.put(mangledComprehensionName, comprehensionEntry.getValue()); + } else { + mangledComprehensionName = + getMangledComprehensionName( + newIterVarPrefix, + newAccuVarPrefix, + comprehensionNode, + comprehensionLevelToType, + comprehensionEntryType); + } + mangledIdentNamesToType.put(mangledComprehensionName, comprehensionEntryType); - CelMutableExpr comprehensionExpr = comprehensionEntry.getKey().expr(); String iterVar = comprehensionExpr.comprehension().iterVar(); String accuVar = comprehensionExpr.comprehension().accuVar(); mutatedComprehensionExpr = @@ -396,6 +428,45 @@ public MangledComprehensionAst mangleComprehensionIdentifierNames( ImmutableMap.copyOf(mangledIdentNamesToType)); } + private static MangledComprehensionName getMangledComprehensionName( + String newIterVarPrefix, + String newResultPrefix, + CelNavigableMutableExpr comprehensionNode, + Table comprehensionLevelToType, + MangledComprehensionType comprehensionEntryType) { + MangledComprehensionName mangledComprehensionName; + int comprehensionNestingLevel = countComprehensionNestingLevel(comprehensionNode); + if (comprehensionLevelToType.contains(comprehensionNestingLevel, comprehensionEntryType)) { + mangledComprehensionName = + comprehensionLevelToType.get(comprehensionNestingLevel, comprehensionEntryType); + } else { + // First time encountering the pair of . Generate a unique + // mangled variable name for this. + int uniqueTypeIdx = comprehensionLevelToType.row(comprehensionNestingLevel).size(); + String mangledIterVarName = + newIterVarPrefix + ":" + comprehensionNestingLevel + ":" + uniqueTypeIdx; + String mangledResultName = + newResultPrefix + ":" + comprehensionNestingLevel + ":" + uniqueTypeIdx; + mangledComprehensionName = MangledComprehensionName.of(mangledIterVarName, mangledResultName); + comprehensionLevelToType.put( + comprehensionNestingLevel, comprehensionEntryType, mangledComprehensionName); + } + return mangledComprehensionName; + } + + private static int countComprehensionNestingLevel(CelNavigableMutableExpr comprehensionExpr) { + int nestedLevel = 0; + Optional maybeParent = comprehensionExpr.parent(); + while (maybeParent.isPresent()) { + if (maybeParent.get().getKind().equals(Kind.COMPREHENSION)) { + nestedLevel++; + } + + maybeParent = maybeParent.get().parent(); + } + return nestedLevel; + } + /** * Replaces a subtree in the given expression node. This operation is intended for AST * optimization purposes. diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java index ecb5b22e4..e6c327915 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java @@ -92,8 +92,8 @@ public class SubexpressionOptimizer implements CelAstOptimizer { private static final SubexpressionOptimizer INSTANCE = new SubexpressionOptimizer(SubexpressionOptimizerOptions.newBuilder().build()); private static final String BIND_IDENTIFIER_PREFIX = "@r"; - private static final String MANGLED_COMPREHENSION_IDENTIFIER_PREFIX = "@c"; - private static final String MANGLED_COMPREHENSION_RESULT_PREFIX = "@x"; + private static final String MANGLED_COMPREHENSION_ITER_VAR_PREFIX = "@it"; + private static final String MANGLED_COMPREHENSION_ACCU_VAR_PREFIX = "@ac"; private static final String CEL_BLOCK_FUNCTION = "cel.@block"; private static final String BLOCK_INDEX_PREFIX = "@index"; private static final Extension CEL_BLOCK_AST_EXTENSION_TAG = @@ -138,8 +138,9 @@ private OptimizationResult optimizeUsingCelBlock(CelAbstractSyntaxTree ast, Cel MangledComprehensionAst mangledComprehensionAst = astMutator.mangleComprehensionIdentifierNames( astToModify, - MANGLED_COMPREHENSION_IDENTIFIER_PREFIX, - MANGLED_COMPREHENSION_RESULT_PREFIX); + MANGLED_COMPREHENSION_ITER_VAR_PREFIX, + MANGLED_COMPREHENSION_ACCU_VAR_PREFIX, + /* incrementSerially= */ false); astToModify = mangledComprehensionAst.mutableAst(); CelMutableSource sourceToModify = astToModify.source(); @@ -339,8 +340,9 @@ private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) { astMutator .mangleComprehensionIdentifierNames( astToModify, - MANGLED_COMPREHENSION_IDENTIFIER_PREFIX, - MANGLED_COMPREHENSION_RESULT_PREFIX) + MANGLED_COMPREHENSION_ITER_VAR_PREFIX, + MANGLED_COMPREHENSION_ACCU_VAR_PREFIX, + /* incrementSerially= */ true) .mutableAst(); CelMutableSource sourceToModify = astToModify.source(); diff --git a/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java b/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java index cdfa1cb00..31cabdb9d 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java @@ -876,14 +876,14 @@ public void mangleComprehensionVariable_singleMacro() throws Exception { CelAbstractSyntaxTree mangledAst = AST_MUTATOR - .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@c", "@x") + .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@it", "@ac", true) .mutableAst() .toParsedAst(); assertThat(mangledAst.getExpr().toString()) .isEqualTo( "COMPREHENSION [13] {\n" - + " iter_var: @c:0\n" + + " iter_var: @it:0\n" + " iter_range: {\n" + " LIST [1] {\n" + " elements: {\n" @@ -891,7 +891,7 @@ public void mangleComprehensionVariable_singleMacro() throws Exception { + " }\n" + " }\n" + " }\n" - + " accu_var: @x:0\n" + + " accu_var: @ac:0\n" + " accu_init: {\n" + " CONSTANT [6] { value: false }\n" + " }\n" @@ -903,7 +903,7 @@ public void mangleComprehensionVariable_singleMacro() throws Exception { + " function: !_\n" + " args: {\n" + " IDENT [7] {\n" - + " name: @x:0\n" + + " name: @ac:0\n" + " }\n" + " }\n" + " }\n" @@ -915,26 +915,69 @@ public void mangleComprehensionVariable_singleMacro() throws Exception { + " function: _||_\n" + " args: {\n" + " IDENT [10] {\n" - + " name: @x:0\n" + + " name: @ac:0\n" + " }\n" + " IDENT [5] {\n" - + " name: @c:0\n" + + " name: @it:0\n" + " }\n" + " }\n" + " }\n" + " }\n" + " result: {\n" + " IDENT [12] {\n" - + " name: @x:0\n" + + " name: @ac:0\n" + " }\n" + " }\n" + "}"); - - assertThat(CEL_UNPARSER.unparse(mangledAst)).isEqualTo("[false].exists(@c:0, @c:0)"); + assertThat(CEL_UNPARSER.unparse(mangledAst)).isEqualTo("[false].exists(@it:0, @it:0)"); assertThat(CEL.createProgram(CEL.check(mangledAst).getAst()).eval()).isEqualTo(false); assertConsistentMacroCalls(ast); } + @Test + public void mangleComprehensionVariable_adjacentMacros_sameIterVarTypes() throws Exception { + CelAbstractSyntaxTree ast = + CEL.compile( + "[1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j +" + + " 1))") + .getAst(); + + CelAbstractSyntaxTree mangledAst = + AST_MUTATOR + .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@it", "@ac", false) + .mutableAst() + .toParsedAst(); + + assertThat(CEL_UNPARSER.unparse(mangledAst)) + .isEqualTo( + "[1, 2, 3].map(@it:0:0, [1, 2, 3].map(@it:1:0, @it:1:0 + 1)) == " + + "[1, 2, 3].map(@it:0:0, [1, 2, 3].map(@it:1:0, @it:1:0 + 1))"); + assertThat(CEL.createProgram(CEL.check(mangledAst).getAst()).eval()).isEqualTo(true); + assertConsistentMacroCalls(ast); + } + + @Test + public void mangleComprehensionVariable_adjacentMacros_differentIterVarTypes() throws Exception { + CelAbstractSyntaxTree ast = + CEL.compile( + "[1,2,3].map(i, [1, 2, 3].map(i, i)) == dyn([1u,2u,3u].map(j, [1u, 2u, 3u].map(j," + + " j)))") + .getAst(); + + CelAbstractSyntaxTree mangledAst = + AST_MUTATOR + .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@it", "@ac", false) + .mutableAst() + .toParsedAst(); + + assertThat(CEL_UNPARSER.unparse(mangledAst)) + .isEqualTo( + "[1, 2, 3].map(@it:0:0, [1, 2, 3].map(@it:1:0, @it:1:0)) == " + + "dyn([1u, 2u, 3u].map(@it:0:1, [1u, 2u, 3u].map(@it:1:1, @it:1:1)))"); + assertThat(CEL.createProgram(CEL.check(mangledAst).getAst()).eval()).isEqualTo(true); + assertConsistentMacroCalls(ast); + } + @Test public void mangleComprehensionVariable_macroSourceDisabled_macroCallMapIsEmpty() throws Exception { @@ -947,7 +990,7 @@ public void mangleComprehensionVariable_macroSourceDisabled_macroCallMapIsEmpty( CelAbstractSyntaxTree mangledAst = AST_MUTATOR - .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@c", "@x") + .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@it", "@ac", true) .mutableAst() .toParsedAst(); @@ -960,14 +1003,14 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw CelAbstractSyntaxTree mangledAst = AST_MUTATOR - .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@c", "@x") + .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@it", "@ac", true) .mutableAst() .toParsedAst(); assertThat(mangledAst.getExpr().toString()) .isEqualTo( "COMPREHENSION [27] {\n" - + " iter_var: @c:1\n" + + " iter_var: @it:1\n" + " iter_range: {\n" + " LIST [1] {\n" + " elements: {\n" @@ -977,7 +1020,7 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " }\n" + " }\n" + " }\n" - + " accu_var: @x:1\n" + + " accu_var: @ac:1\n" + " accu_init: {\n" + " CONSTANT [20] { value: false }\n" + " }\n" @@ -989,7 +1032,7 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " function: !_\n" + " args: {\n" + " IDENT [21] {\n" - + " name: @x:1\n" + + " name: @ac:1\n" + " }\n" + " }\n" + " }\n" @@ -1001,20 +1044,20 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " function: _||_\n" + " args: {\n" + " IDENT [24] {\n" - + " name: @x:1\n" + + " name: @ac:1\n" + " }\n" + " COMPREHENSION [19] {\n" - + " iter_var: @c:0\n" + + " iter_var: @it:0\n" + " iter_range: {\n" + " LIST [5] {\n" + " elements: {\n" + " IDENT [6] {\n" - + " name: @c:1\n" + + " name: @it:1\n" + " }\n" + " }\n" + " }\n" + " }\n" - + " accu_var: @x:0\n" + + " accu_var: @ac:0\n" + " accu_init: {\n" + " CONSTANT [12] { value: false }\n" + " }\n" @@ -1026,7 +1069,7 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " function: !_\n" + " args: {\n" + " IDENT [13] {\n" - + " name: @x:0\n" + + " name: @ac:0\n" + " }\n" + " }\n" + " }\n" @@ -1038,13 +1081,13 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " function: _||_\n" + " args: {\n" + " IDENT [16] {\n" - + " name: @x:0\n" + + " name: @ac:0\n" + " }\n" + " CALL [10] {\n" + " function: _==_\n" + " args: {\n" + " IDENT [9] {\n" - + " name: @c:0\n" + + " name: @it:0\n" + " }\n" + " CONSTANT [11] { value: 1 }\n" + " }\n" @@ -1054,7 +1097,7 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " }\n" + " result: {\n" + " IDENT [18] {\n" - + " name: @x:0\n" + + " name: @ac:0\n" + " }\n" + " }\n" + " }\n" @@ -1063,13 +1106,13 @@ public void mangleComprehensionVariable_nestedMacroWithShadowedVariables() throw + " }\n" + " result: {\n" + " IDENT [26] {\n" - + " name: @x:1\n" + + " name: @ac:1\n" + " }\n" + " }\n" + "}"); assertThat(CEL_UNPARSER.unparse(mangledAst)) - .isEqualTo("[x].exists(@c:1, [@c:1].exists(@c:0, @c:0 == 1))"); + .isEqualTo("[x].exists(@it:1, [@it:1].exists(@it:0, @it:0 == 1))"); assertThat(CEL.createProgram(CEL.check(mangledAst).getAst()).eval(ImmutableMap.of("x", 1))) .isEqualTo(true); assertConsistentMacroCalls(ast); @@ -1081,7 +1124,7 @@ public void mangleComprehensionVariable_hasMacro_noOp() throws Exception { CelAbstractSyntaxTree mangledAst = AST_MUTATOR - .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@c", "@x") + .mangleComprehensionIdentifierNames(CelMutableAst.fromCelAst(ast), "@it", "@ac", true) .mutableAst() .toParsedAst(); diff --git a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline index 897b4d775..7324d1716 100644 --- a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline @@ -418,17 +418,17 @@ Test case: MACRO_SHADOWED_VARIABLE Source: [x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3 =====> Result: true -[CASCADED_BINDS]: cel.bind(@r0, x - 1, cel.bind(@r1, @r0 > 3, [@r1 ? @r0 : 5].exists(@c:0, @c:0 - 1 > 3) || @r1)) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@c:0, @c:0 - 1 > 3) || @index1) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([x - 1, @index0 > 3, @index1 ? @index0 : 5, [@index2], @c:0 - 1, @index4 > 3, @x:0 || @index5], @index3.exists(@c:0, @index5) || @index1) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([x - 1 > 3, @index0 ? (x - 1) : 5, @c:0 - 1 > 3, [@index1], @x:0 || @index2], @index3.exists(@c:0, @index2) || @index0) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5], @x:0 || @c:0 - 1 > 3, @index1.exists(@c:0, @c:0 - 1 > 3)], @index3 || @index0) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3)], @index1 || @index0) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) +[CASCADED_BINDS]: cel.bind(@r0, x - 1, cel.bind(@r1, @r0 > 3, [@r1 ? @r0 : 5].exists(@it:0, @it:0 - 1 > 3) || @r1)) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index1) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([x - 1, @index0 > 3, @index1 ? @index0 : 5, [@index2], @it:0:0 - 1, @index4 > 3, @ac:0:0 || @index5], @index3.exists(@it:0:0, @index5) || @index1) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([x - 1 > 3, @index0 ? (x - 1) : 5, @it:0:0 - 1 > 3, [@index1], @ac:0:0 || @index2], @index3.exists(@it:0:0, @index2) || @index0) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5], @ac:0:0 || @it:0:0 - 1 > 3, @index1.exists(@it:0:0, @it:0:0 - 1 > 3)], @index3 || @index0) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3)], @index1 || @index0) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) Test case: MACRO_SHADOWED_VARIABLE_2 Source: ["foo", "bar"].map(x, [x + x, x + x]).map(x, [x + x, x + x]) diff --git a/optimizer/src/test/resources/large_expressions_bind_cascaded.baseline b/optimizer/src/test/resources/large_expressions_bind_cascaded.baseline index a37fd38ce..cec9eec5d 100644 --- a/optimizer/src/test/resources/large_expressions_bind_cascaded.baseline +++ b/optimizer/src/test/resources/large_expressions_bind_cascaded.baseline @@ -14,4 +14,4 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3])))))))) =====> Result: [[[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]]] -Unparsed: cel.bind(@r0, [1, 2, 3], @r0.map(@c:7, @r0.map(@c:6, @r0.map(@c:5, @r0.map(@c:4, @r0.map(@c:3, @r0.map(@c:2, @r0.map(@c:1, @r0.map(@c:0, @r0))))))))) \ No newline at end of file +Unparsed: cel.bind(@r0, [1, 2, 3], @r0.map(@it:7, @r0.map(@it:6, @r0.map(@it:5, @r0.map(@it:4, @r0.map(@it:3, @r0.map(@it:2, @r0.map(@it:1, @r0.map(@it:0, @r0))))))))) \ No newline at end of file diff --git a/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline b/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline index 35a169875..87623446d 100644 --- a/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline +++ b/optimizer/src/test/resources/large_expressions_block_common_subexpr.baseline @@ -14,4 +14,4 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3])))))))) =====> Result: [[[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]]] -Unparsed: cel.@block([[1, 2, 3]], @index0.map(@c:7, @index0.map(@c:6, @index0.map(@c:5, @index0.map(@c:4, @index0.map(@c:3, @index0.map(@c:2, @index0.map(@c:1, @index0.map(@c:0, @index0))))))))) \ No newline at end of file +Unparsed: cel.@block([[1, 2, 3]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index0.map(@it:2:0, @index0.map(@it:3:0, @index0.map(@it:4:0, @index0.map(@it:5:0, @index0.map(@it:6:0, @index0.map(@it:7:0, @index0))))))))) \ No newline at end of file diff --git a/optimizer/src/test/resources/large_expressions_block_recursion_depth_1.baseline b/optimizer/src/test/resources/large_expressions_block_recursion_depth_1.baseline index 7409190cc..8dd1445eb 100644 --- a/optimizer/src/test/resources/large_expressions_block_recursion_depth_1.baseline +++ b/optimizer/src/test/resources/large_expressions_block_recursion_depth_1.baseline @@ -14,4 +14,4 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3])))))))) =====> Result: [[[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]]] -Unparsed: cel.@block([[1, 2, 3], [@index0], @x:0 + @index1], @index0.map(@c:7, @index0.map(@c:6, @index0.map(@c:5, @index0.map(@c:4, @index0.map(@c:3, @index0.map(@c:2, @index0.map(@c:1, @index0.map(@c:0, @index0))))))))) \ No newline at end of file +Unparsed: cel.@block([[1, 2, 3], [@index0], @ac:7:0 + @index1], @index0.map(@it:0:0, @index0.map(@it:1:0, @index0.map(@it:2:0, @index0.map(@it:3:0, @index0.map(@it:4:0, @index0.map(@it:5:0, @index0.map(@it:6:0, @index0.map(@it:7:0, @index0))))))))) \ No newline at end of file diff --git a/optimizer/src/test/resources/large_expressions_block_recursion_depth_2.baseline b/optimizer/src/test/resources/large_expressions_block_recursion_depth_2.baseline index 01fe95991..f139abe3c 100644 --- a/optimizer/src/test/resources/large_expressions_block_recursion_depth_2.baseline +++ b/optimizer/src/test/resources/large_expressions_block_recursion_depth_2.baseline @@ -14,4 +14,4 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3])))))))) =====> Result: [[[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]]] -Unparsed: cel.@block([[1, 2, 3], @x:0 + [@index0], @index0.map(@c:0, @index0), @x:1 + [@index2], @index0.map(@c:1, @index2), @x:2 + [@index4], @index0.map(@c:2, @index4), @x:3 + [@index6], @index0.map(@c:3, @index6), @x:4 + [@index8], @index0.map(@c:4, @index8), @x:5 + [@index10], @index0.map(@c:5, @index10), @x:6 + [@index12], @index0.map(@c:6, @index12), @x:7 + [@index14]], @index0.map(@c:7, @index14)) \ No newline at end of file +Unparsed: cel.@block([[1, 2, 3], @ac:7:0 + [@index0], @index0.map(@it:7:0, @index0), @ac:6:0 + [@index2], @index0.map(@it:6:0, @index2), @ac:5:0 + [@index4], @index0.map(@it:5:0, @index4), @ac:4:0 + [@index6], @index0.map(@it:4:0, @index6), @ac:3:0 + [@index8], @index0.map(@it:3:0, @index8), @ac:2:0 + [@index10], @index0.map(@it:2:0, @index10), @ac:1:0 + [@index12], @index0.map(@it:1:0, @index12), @ac:0:0 + [@index14]], @index0.map(@it:0:0, @index14)) \ No newline at end of file diff --git a/optimizer/src/test/resources/large_expressions_block_recursion_depth_3.baseline b/optimizer/src/test/resources/large_expressions_block_recursion_depth_3.baseline index 56d163470..3ce295592 100644 --- a/optimizer/src/test/resources/large_expressions_block_recursion_depth_3.baseline +++ b/optimizer/src/test/resources/large_expressions_block_recursion_depth_3.baseline @@ -14,4 +14,4 @@ Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3].map(i, [1, 2, 3])))))))) =====> Result: [[[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]], [[[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]], [[[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]], [[[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]], [[[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]], [[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]], [[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]]]]]]] -Unparsed: cel.@block([[1, 2, 3], @index0.map(@c:0, @index0), @index0.map(@c:1, @index1), @index0.map(@c:2, @index2), @index0.map(@c:3, @index3), @index0.map(@c:4, @index4), @index0.map(@c:5, @index5), @index0.map(@c:6, @index6)], @index0.map(@c:7, @index7)) \ No newline at end of file +Unparsed: cel.@block([[1, 2, 3], @index0.map(@it:7:0, @index0), @index0.map(@it:6:0, @index1), @index0.map(@it:5:0, @index2), @index0.map(@it:4:0, @index3), @index0.map(@it:3:0, @index4), @index0.map(@it:2:0, @index5), @index0.map(@it:1:0, @index6)], @index0.map(@it:0:0, @index7)) \ No newline at end of file diff --git a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline index d2267c0d8..292b584f6 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline @@ -1116,504 +1116,95 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - } - } - CALL [7] { - function: _==_ - args: { - CALL [8] { - function: _+_ + CALL [3] { + function: size args: { - CALL [9] { - function: _+_ - args: { - CALL [10] { - function: _+_ - args: { - CALL [11] { - function: size - args: { - LIST [12] { - elements: { - COMPREHENSION [13] { - iter_var: @c:0 - iter_range: { - IDENT [14] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [15] { value: false } - } - loop_condition: { - CALL [16] { - function: @not_strictly_false - args: { - CALL [17] { - function: !_ - args: { - IDENT [18] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [19] { - function: _||_ - args: { - IDENT [20] { - name: @x:0 - } - CALL [21] { - function: _>_ - args: { - IDENT [22] { - name: @c:0 - } - CONSTANT [23] { value: 0 } - } - } - } - } - } - result: { - IDENT [24] { - name: @x:0 - } - } - } - } - } - } - } - CALL [25] { - function: size - args: { - LIST [26] { - elements: { - COMPREHENSION [27] { - iter_var: @c:1 - iter_range: { - IDENT [28] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [29] { value: false } - } - loop_condition: { - CALL [30] { - function: @not_strictly_false - args: { - CALL [31] { - function: !_ - args: { - IDENT [32] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [33] { - function: _||_ - args: { - IDENT [34] { - name: @x:1 - } - CALL [35] { - function: _>_ - args: { - IDENT [36] { - name: @c:1 - } - CONSTANT [37] { value: 0 } - } - } - } - } - } - result: { - IDENT [38] { - name: @x:1 - } - } - } - } - } - } - } - } - } - CALL [39] { - function: size - args: { - LIST [40] { + LIST [4] { + elements: { + COMPREHENSION [5] { + iter_var: @it:0:0 + iter_range: { + LIST [6] { elements: { - COMPREHENSION [41] { - iter_var: @c:2 - iter_range: { - IDENT [42] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [43] { value: false } - } - loop_condition: { - CALL [44] { - function: @not_strictly_false - args: { - CALL [45] { - function: !_ - args: { - IDENT [46] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [47] { - function: _||_ - args: { - IDENT [48] { - name: @x:2 - } - CALL [49] { - function: _>_ - args: { - IDENT [50] { - name: @c:2 - } - CONSTANT [51] { value: 1 } - } - } - } - } - } - result: { - IDENT [52] { - name: @x:2 - } - } - } + CONSTANT [7] { value: 1 } } } } - } - } - } - CALL [53] { - function: size - args: { - LIST [54] { - elements: { - COMPREHENSION [55] { - iter_var: @c:3 - iter_range: { - IDENT [56] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [57] { value: false } - } - loop_condition: { - CALL [58] { - function: @not_strictly_false - args: { - CALL [59] { - function: !_ - args: { - IDENT [60] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [61] { - function: _||_ + accu_var: @ac:0:0 + accu_init: { + CONSTANT [8] { value: false } + } + loop_condition: { + CALL [9] { + function: @not_strictly_false + args: { + CALL [10] { + function: !_ args: { - IDENT [62] { - name: @x:3 - } - CALL [63] { - function: _>_ - args: { - IDENT [64] { - name: @c:3 - } - CONSTANT [65] { value: 1 } - } + IDENT [11] { + name: @ac:0:0 } } } } - result: { - IDENT [66] { - name: @x:3 - } - } } } - } - } - } - } - } - CONSTANT [67] { value: 4 } - } - } - } -} -Test case: MULTIPLE_MACROS_2 -Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] -=====> -CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - } - } - CALL [7] { - function: _==_ - args: { - CALL [8] { - function: _+_ - args: { - CALL [9] { - function: _+_ - args: { - CALL [10] { - function: _+_ - args: { - LIST [11] { - elements: { - COMPREHENSION [12] { - iter_var: @c:0 - iter_range: { - IDENT [13] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [14] { value: false } - } - loop_condition: { - CALL [15] { - function: @not_strictly_false - args: { - CALL [16] { - function: !_ - args: { - IDENT [17] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [18] { - function: _||_ - args: { - IDENT [19] { - name: @x:0 - } - CALL [20] { - function: _>_ - args: { - IDENT [21] { - name: @c:0 - } - CONSTANT [22] { value: 0 } - } - } - } - } - } - result: { - IDENT [23] { - name: @x:0 - } - } + loop_step: { + CALL [12] { + function: _||_ + args: { + IDENT [13] { + name: @ac:0:0 } - } - } - LIST [24] { - elements: { - COMPREHENSION [25] { - iter_var: @c:1 - iter_range: { - IDENT [26] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [27] { value: false } - } - loop_condition: { - CALL [28] { - function: @not_strictly_false - args: { - CALL [29] { - function: !_ - args: { - IDENT [30] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [31] { - function: _||_ - args: { - IDENT [32] { - name: @x:1 - } - CALL [33] { - function: _>_ - args: { - IDENT [34] { - name: @c:1 - } - CONSTANT [35] { value: 0 } - } - } - } - } - } - result: { - IDENT [36] { - name: @x:1 + CALL [14] { + function: _>_ + args: { + IDENT [15] { + name: @it:0:0 } + CONSTANT [16] { value: 0 } } } } } } - } - LIST [37] { - elements: { - COMPREHENSION [38] { - iter_var: @c:2 - iter_range: { - IDENT [39] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [40] { value: false } - } - loop_condition: { - CALL [41] { - function: @not_strictly_false - args: { - CALL [42] { - function: !_ - args: { - IDENT [43] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [44] { - function: _||_ - args: { - IDENT [45] { - name: @x:2 - } - CALL [46] { - function: _==_ - args: { - IDENT [47] { - name: @c:2 - } - CONSTANT [48] { value: "a" } - } - } - } - } - } - result: { - IDENT [49] { - name: @x:2 - } - } + result: { + IDENT [17] { + name: @ac:0:0 } } } } } - LIST [50] { + } + } + CALL [18] { + function: size + args: { + LIST [19] { elements: { - COMPREHENSION [51] { - iter_var: @c:3 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [52] { - name: @index1 + LIST [21] { + elements: { + CONSTANT [22] { value: 2 } + } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [53] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [54] { + CALL [24] { function: @not_strictly_false args: { - CALL [55] { + CALL [25] { function: !_ args: { - IDENT [56] { - name: @x:3 + IDENT [26] { + name: @ac:0:0 } } } @@ -1621,27 +1212,27 @@ CALL [1] { } } loop_step: { - CALL [57] { + CALL [27] { function: _||_ args: { - IDENT [58] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } - CALL [59] { - function: _==_ + CALL [29] { + function: _>_ args: { - IDENT [60] { - name: @c:3 + IDENT [30] { + name: @it:0:0 } - CONSTANT [61] { value: "a" } + CONSTANT [31] { value: 1 } } } } } } result: { - IDENT [62] { - name: @x:3 + IDENT [32] { + name: @ac:0:0 } } } @@ -1649,20 +1240,45 @@ CALL [1] { } } } - LIST [63] { - elements: { - CONSTANT [64] { value: true } - CONSTANT [65] { value: true } - CONSTANT [66] { value: true } - CONSTANT [67] { value: true } + } + } + CALL [33] { + function: _==_ + args: { + CALL [34] { + function: _+_ + args: { + CALL [35] { + function: _+_ + args: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @index0 + } + IDENT [38] { + name: @index0 + } + } + } + IDENT [39] { + name: @index1 + } + } + } + IDENT [40] { + name: @index1 + } } } + CONSTANT [41] { value: 4 } } } } } -Test case: MULTIPLE_MACROS_3 -Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> CALL [1] { function: cel.@block @@ -1671,37 +1287,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - } - } - CALL [5] { - function: _&&_ - args: { - CALL [6] { - function: _&&_ - args: { - COMPREHENSION [7] { - iter_var: @c:0 + COMPREHENSION [4] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [10] { + CALL [8] { function: @not_strictly_false args: { - CALL [11] { + CALL [9] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1709,38 +1316,44 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [11] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [15] { + CALL [13] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + } + } + LIST [17] { + elements: { + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { CONSTANT [21] { value: false } } @@ -1752,7 +1365,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:1 } } } @@ -1764,15 +1377,15 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:1 } CALL [27] { - function: _>_ + function: _==_ args: { IDENT [28] { - name: @c:1 + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [29] { value: "a" } } } } @@ -1780,35 +1393,175 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:1 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + CALL [32] { + function: _+_ + args: { + CALL [33] { + function: _+_ + args: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @index0 + } + IDENT [36] { + name: @index0 + } + } + } + IDENT [37] { + name: @index1 + } + } + } + IDENT [38] { + name: @index1 + } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [31] { + } + } + CALL [21] { + function: _&&_ + args: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @index0 + } + IDENT [24] { + name: @index0 + } + } + } + CALL [25] { function: _&&_ args: { - COMPREHENSION [32] { - iter_var: @c:2 + COMPREHENSION [26] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 + LIST [27] { + elements: { + CONSTANT [28] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [34] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [35] { + CALL [30] { function: @not_strictly_false args: { - CALL [36] { + CALL [31] { function: !_ args: { - IDENT [37] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1816,52 +1569,38 @@ CALL [1] { } } loop_step: { - CALL [38] { - function: _||_ - args: { - IDENT [39] { - name: @x:2 - } - CALL [40] { - function: _>_ - args: { - IDENT [41] { - name: @c:2 - } - CONSTANT [42] { value: 1 } - } - } - } + IDENT [33] { + name: @index1 } } result: { - IDENT [43] { - name: @x:2 + IDENT [34] { + name: @ac:0:0 } } } - COMPREHENSION [44] { - iter_var: @c:3 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - LIST [45] { + LIST [36] { elements: { - CONSTANT [46] { value: 2 } + CONSTANT [37] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [47] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [48] { + CALL [39] { function: @not_strictly_false args: { - CALL [49] { + CALL [40] { function: !_ args: { - IDENT [50] { - name: @x:3 + IDENT [41] { + name: @ac:0:0 } } } @@ -1869,27 +1608,13 @@ CALL [1] { } } loop_step: { - CALL [51] { - function: _||_ - args: { - IDENT [52] { - name: @x:3 - } - CALL [53] { - function: _>_ - args: { - IDENT [54] { - name: @c:3 - } - CONSTANT [55] { value: 1 } - } - } - } + IDENT [42] { + name: @index1 } } result: { - IDENT [56] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -1927,13 +1652,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [12] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [13] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [14] { elements: { @@ -1948,18 +1673,18 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:1 + name: @ac:0:0 } LIST [18] { elements: { COMPREHENSION [19] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [20] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [21] { elements: { @@ -1974,7 +1699,7 @@ CALL [1] { function: _+_ args: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } LIST [25] { elements: { @@ -1982,7 +1707,7 @@ CALL [1] { function: _+_ args: { IDENT [27] { - name: @c:0 + name: @it:1:0 } CONSTANT [28] { value: 1 } } @@ -1994,7 +1719,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:0 + name: @ac:1:0 } } } @@ -2005,7 +1730,7 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:0 } } } @@ -2033,7 +1758,7 @@ CALL [31] { function: _==_ args: { COMPREHENSION [30] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [1] { elements: { @@ -2042,7 +1767,7 @@ CALL [31] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [24] { elements: { @@ -2057,12 +1782,12 @@ CALL [31] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { COMPREHENSION [23] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [6] { elements: { @@ -2072,7 +1797,7 @@ CALL [31] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [15] { elements: { @@ -2090,10 +1815,10 @@ CALL [31] { function: _==_ args: { IDENT [12] { - name: @c:0 + name: @it:1:0 } IDENT [14] { - name: @c:1 + name: @it:0:0 } } } @@ -2101,26 +1826,26 @@ CALL [31] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { IDENT [11] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [20] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -2131,7 +1856,7 @@ CALL [31] { } result: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } } } @@ -2166,70 +1891,65 @@ CALL [1] { CONSTANT [6] { value: 3 } } } - } - } - CALL [7] { - function: _==_ - args: { - COMPREHENSION [8] { - iter_var: @c:1 + COMPREHENSION [7] { + iter_var: @it:0:0 iter_range: { - IDENT [9] { + IDENT [8] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - LIST [10] { + LIST [9] { elements: { } } } loop_condition: { - CONSTANT [11] { value: true } + CONSTANT [10] { value: true } } loop_step: { - CALL [12] { + CALL [11] { function: _+_ args: { - IDENT [13] { - name: @x:1 + IDENT [12] { + name: @ac:0:0 } - LIST [14] { + LIST [13] { elements: { - COMPREHENSION [15] { - iter_var: @c:0 + COMPREHENSION [14] { + iter_var: @it:1:0 iter_range: { - IDENT [16] { + IDENT [15] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { - LIST [17] { + LIST [16] { elements: { } } } loop_condition: { - CONSTANT [18] { value: true } + CONSTANT [17] { value: true } } loop_step: { - CALL [19] { + CALL [18] { function: _+_ args: { - IDENT [20] { - name: @x:0 + IDENT [19] { + name: @ac:1:0 } - LIST [21] { + LIST [20] { elements: { - CALL [22] { + CALL [21] { function: _+_ args: { - IDENT [23] { - name: @c:0 + IDENT [22] { + name: @it:1:0 } - CONSTANT [24] { value: 1 } + CONSTANT [23] { value: 1 } } } } @@ -2238,8 +1958,8 @@ CALL [1] { } } result: { - IDENT [25] { - name: @x:0 + IDENT [24] { + name: @ac:1:0 } } } @@ -2249,93 +1969,21 @@ CALL [1] { } } result: { - IDENT [26] { - name: @x:1 + IDENT [25] { + name: @ac:0:0 } } } - COMPREHENSION [27] { - iter_var: @c:3 - iter_range: { - IDENT [28] { - name: @index0 - } - } - accu_var: @x:3 - accu_init: { - LIST [29] { - elements: { - } - } - } - loop_condition: { - CONSTANT [30] { value: true } - } - loop_step: { - CALL [31] { - function: _+_ - args: { - IDENT [32] { - name: @x:3 - } - LIST [33] { - elements: { - COMPREHENSION [34] { - iter_var: @c:2 - iter_range: { - IDENT [35] { - name: @index0 - } - } - accu_var: @x:2 - accu_init: { - LIST [36] { - elements: { - } - } - } - loop_condition: { - CONSTANT [37] { value: true } - } - loop_step: { - CALL [38] { - function: _+_ - args: { - IDENT [39] { - name: @x:2 - } - LIST [40] { - elements: { - CALL [41] { - function: _+_ - args: { - IDENT [42] { - name: @c:2 - } - CONSTANT [43] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [44] { - name: @x:2 - } - } - } - } - } - } - } - } - result: { - IDENT [45] { - name: @x:3 - } - } + } + } + CALL [26] { + function: _==_ + args: { + IDENT [27] { + name: @index1 + } + IDENT [28] { + name: @index1 } } } @@ -2507,13 +2155,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [13] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [14] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [15] { elements: { @@ -2528,18 +2176,18 @@ CALL [1] { function: _+_ args: { IDENT [18] { - name: @x:1 + name: @ac:0:0 } LIST [19] { elements: { COMPREHENSION [20] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [21] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [22] { elements: { @@ -2554,7 +2202,7 @@ CALL [1] { function: _+_ args: { IDENT [25] { - name: @x:0 + name: @ac:1:0 } LIST [26] { elements: { @@ -2568,7 +2216,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:1:0 } } } @@ -2579,7 +2227,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } } } @@ -2629,7 +2277,7 @@ CALL [1] { function: _||_ args: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [11] { elements: { @@ -2648,7 +2296,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [16] { value: false } } @@ -2660,7 +2308,7 @@ CALL [1] { function: !_ args: { IDENT [19] { - name: @x:0 + name: @ac:0:0 } } } @@ -2672,7 +2320,7 @@ CALL [1] { function: _||_ args: { IDENT [21] { - name: @x:0 + name: @ac:0:0 } CALL [22] { function: _>_ @@ -2681,7 +2329,7 @@ CALL [1] { function: _-_ args: { IDENT [24] { - name: @c:0 + name: @it:0:0 } CONSTANT [25] { value: 1 } } @@ -2694,7 +2342,7 @@ CALL [1] { } result: { IDENT [27] { - name: @x:0 + name: @ac:0:0 } } } @@ -2717,10 +2365,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2728,20 +2376,20 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } } } COMPREHENSION [9] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [11] { elements: { @@ -2750,7 +2398,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2765,7 +2413,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2786,12 +2434,12 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -2806,7 +2454,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2827,7 +2475,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline index bcfc70fb1..070df4db9 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline @@ -1436,130 +1436,90 @@ CALL [1] { CONSTANT [4] { value: 1 } } } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - CALL [7] { + CALL [5] { function: _>_ args: { - IDENT [8] { - name: @c:0 + IDENT [6] { + name: @it:0:0 } - CONSTANT [9] { value: 0 } + CONSTANT [7] { value: 0 } } } - CALL [10] { + CALL [8] { function: _||_ args: { - IDENT [11] { - name: @x:0 + IDENT [9] { + name: @ac:0:0 } - IDENT [12] { - name: @index2 + IDENT [10] { + name: @index1 } } } + LIST [11] { + elements: { + CONSTANT [12] { value: 2 } + } + } CALL [13] { function: _>_ args: { IDENT [14] { - name: @c:1 + name: @it:0:0 } - CONSTANT [15] { value: 0 } + CONSTANT [15] { value: 1 } } } CALL [16] { function: _||_ args: { IDENT [17] { - name: @x:1 + name: @ac:0:0 } IDENT [18] { name: @index4 } } } - CALL [19] { - function: _>_ - args: { - IDENT [20] { - name: @c:2 - } - CONSTANT [21] { value: 1 } - } - } - CALL [22] { - function: _||_ - args: { - IDENT [23] { - name: @x:2 - } - IDENT [24] { - name: @index6 - } - } - } - CALL [25] { - function: _>_ - args: { - IDENT [26] { - name: @c:3 - } - CONSTANT [27] { value: 1 } - } - } - CALL [28] { - function: _||_ - args: { - IDENT [29] { - name: @x:3 - } - IDENT [30] { - name: @index8 - } - } - } } } - CALL [31] { + CALL [19] { function: _==_ args: { - CALL [32] { + CALL [20] { function: _+_ args: { - CALL [33] { + CALL [21] { function: _+_ args: { - CALL [34] { + CALL [22] { function: _+_ args: { - CALL [35] { + CALL [23] { function: size args: { - LIST [36] { + LIST [24] { elements: { - COMPREHENSION [37] { - iter_var: @c:0 + COMPREHENSION [25] { + iter_var: @it:0:0 iter_range: { - IDENT [38] { + IDENT [26] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [39] { value: false } + CONSTANT [27] { value: false } } loop_condition: { - CALL [40] { + CALL [28] { function: @not_strictly_false args: { - CALL [41] { + CALL [29] { function: !_ args: { - IDENT [42] { - name: @x:0 + IDENT [30] { + name: @ac:0:0 } } } @@ -1567,13 +1527,13 @@ CALL [1] { } } loop_step: { - IDENT [43] { - name: @index3 + IDENT [31] { + name: @index2 } } result: { - IDENT [44] { - name: @x:0 + IDENT [32] { + name: @ac:0:0 } } } @@ -1581,31 +1541,31 @@ CALL [1] { } } } - CALL [45] { + CALL [33] { function: size args: { - LIST [46] { + LIST [34] { elements: { - COMPREHENSION [47] { - iter_var: @c:1 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - IDENT [48] { + IDENT [36] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [49] { value: false } + CONSTANT [37] { value: false } } loop_condition: { - CALL [50] { + CALL [38] { function: @not_strictly_false args: { - CALL [51] { + CALL [39] { function: !_ args: { - IDENT [52] { - name: @x:1 + IDENT [40] { + name: @ac:0:0 } } } @@ -1613,13 +1573,13 @@ CALL [1] { } } loop_step: { - IDENT [53] { - name: @index5 + IDENT [41] { + name: @index2 } } result: { - IDENT [54] { - name: @x:1 + IDENT [42] { + name: @ac:0:0 } } } @@ -1629,31 +1589,31 @@ CALL [1] { } } } - CALL [55] { + CALL [43] { function: size args: { - LIST [56] { + LIST [44] { elements: { - COMPREHENSION [57] { - iter_var: @c:2 + COMPREHENSION [45] { + iter_var: @it:0:0 iter_range: { - IDENT [58] { - name: @index1 + IDENT [46] { + name: @index3 } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [59] { value: false } + CONSTANT [47] { value: false } } loop_condition: { - CALL [60] { + CALL [48] { function: @not_strictly_false args: { - CALL [61] { + CALL [49] { function: !_ args: { - IDENT [62] { - name: @x:2 + IDENT [50] { + name: @ac:0:0 } } } @@ -1661,13 +1621,13 @@ CALL [1] { } } loop_step: { - IDENT [63] { - name: @index7 + IDENT [51] { + name: @index5 } } result: { - IDENT [64] { - name: @x:2 + IDENT [52] { + name: @ac:0:0 } } } @@ -1677,31 +1637,31 @@ CALL [1] { } } } - CALL [65] { + CALL [53] { function: size args: { - LIST [66] { + LIST [54] { elements: { - COMPREHENSION [67] { - iter_var: @c:3 + COMPREHENSION [55] { + iter_var: @it:0:0 iter_range: { - IDENT [68] { - name: @index1 + IDENT [56] { + name: @index3 } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [69] { value: false } + CONSTANT [57] { value: false } } loop_condition: { - CALL [70] { + CALL [58] { function: @not_strictly_false args: { - CALL [71] { + CALL [59] { function: !_ args: { - IDENT [72] { - name: @x:3 + IDENT [60] { + name: @ac:0:0 } } } @@ -1709,13 +1669,13 @@ CALL [1] { } } loop_step: { - IDENT [73] { - name: @index9 + IDENT [61] { + name: @index5 } } result: { - IDENT [74] { - name: @x:3 + IDENT [62] { + name: @ac:0:0 } } } @@ -1725,7 +1685,7 @@ CALL [1] { } } } - CONSTANT [75] { value: 4 } + CONSTANT [63] { value: 4 } } } } @@ -1743,135 +1703,95 @@ CALL [1] { CONSTANT [4] { value: 1 } } } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - CALL [7] { + CALL [5] { function: _>_ args: { - IDENT [8] { - name: @c:0 + IDENT [6] { + name: @it:0:0 } - CONSTANT [9] { value: 0 } + CONSTANT [7] { value: 0 } } } - CALL [10] { + CALL [8] { function: _||_ args: { - IDENT [11] { - name: @x:0 + IDENT [9] { + name: @ac:0:0 } - IDENT [12] { - name: @index2 + IDENT [10] { + name: @index1 } } } + LIST [11] { + elements: { + CONSTANT [12] { value: "a" } + } + } CALL [13] { - function: _>_ + function: _==_ args: { IDENT [14] { - name: @c:1 + name: @it:0:1 } - CONSTANT [15] { value: 0 } + CONSTANT [15] { value: "a" } } } CALL [16] { function: _||_ args: { IDENT [17] { - name: @x:1 + name: @ac:0:1 } IDENT [18] { name: @index4 } } } - CALL [19] { - function: _==_ - args: { - IDENT [20] { - name: @c:2 - } - CONSTANT [21] { value: "a" } - } - } - CALL [22] { - function: _||_ - args: { - IDENT [23] { - name: @x:2 - } - IDENT [24] { - name: @index6 - } - } - } - CALL [25] { - function: _==_ - args: { - IDENT [26] { - name: @c:3 - } - CONSTANT [27] { value: "a" } - } - } - CALL [28] { - function: _||_ - args: { - IDENT [29] { - name: @x:3 - } - IDENT [30] { - name: @index8 - } - } - } - LIST [31] { + LIST [19] { elements: { - CONSTANT [32] { value: true } - CONSTANT [33] { value: true } - CONSTANT [34] { value: true } - CONSTANT [35] { value: true } + CONSTANT [20] { value: true } + CONSTANT [21] { value: true } + CONSTANT [22] { value: true } + CONSTANT [23] { value: true } } } } } - CALL [36] { + CALL [24] { function: _==_ args: { - CALL [37] { + CALL [25] { function: _+_ args: { - CALL [38] { + CALL [26] { function: _+_ args: { - CALL [39] { + CALL [27] { function: _+_ args: { - LIST [40] { + LIST [28] { elements: { - COMPREHENSION [41] { - iter_var: @c:0 + COMPREHENSION [29] { + iter_var: @it:0:0 iter_range: { - IDENT [42] { + IDENT [30] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [43] { value: false } + CONSTANT [31] { value: false } } loop_condition: { - CALL [44] { + CALL [32] { function: @not_strictly_false args: { - CALL [45] { + CALL [33] { function: !_ args: { - IDENT [46] { - name: @x:0 + IDENT [34] { + name: @ac:0:0 } } } @@ -1879,40 +1799,40 @@ CALL [1] { } } loop_step: { - IDENT [47] { - name: @index3 + IDENT [35] { + name: @index2 } } result: { - IDENT [48] { - name: @x:0 + IDENT [36] { + name: @ac:0:0 } } } } } - LIST [49] { + LIST [37] { elements: { - COMPREHENSION [50] { - iter_var: @c:1 + COMPREHENSION [38] { + iter_var: @it:0:0 iter_range: { - IDENT [51] { + IDENT [39] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [52] { value: false } + CONSTANT [40] { value: false } } loop_condition: { - CALL [53] { + CALL [41] { function: @not_strictly_false args: { - CALL [54] { + CALL [42] { function: !_ args: { - IDENT [55] { - name: @x:1 + IDENT [43] { + name: @ac:0:0 } } } @@ -1920,13 +1840,13 @@ CALL [1] { } } loop_step: { - IDENT [56] { - name: @index5 + IDENT [44] { + name: @index2 } } result: { - IDENT [57] { - name: @x:1 + IDENT [45] { + name: @ac:0:0 } } } @@ -1934,28 +1854,28 @@ CALL [1] { } } } - LIST [58] { + LIST [46] { elements: { - COMPREHENSION [59] { - iter_var: @c:2 + COMPREHENSION [47] { + iter_var: @it:0:1 iter_range: { - IDENT [60] { - name: @index1 + IDENT [48] { + name: @index3 } } - accu_var: @x:2 + accu_var: @ac:0:1 accu_init: { - CONSTANT [61] { value: false } + CONSTANT [49] { value: false } } loop_condition: { - CALL [62] { + CALL [50] { function: @not_strictly_false args: { - CALL [63] { + CALL [51] { function: !_ args: { - IDENT [64] { - name: @x:2 + IDENT [52] { + name: @ac:0:1 } } } @@ -1963,13 +1883,13 @@ CALL [1] { } } loop_step: { - IDENT [65] { - name: @index7 + IDENT [53] { + name: @index5 } } result: { - IDENT [66] { - name: @x:2 + IDENT [54] { + name: @ac:0:1 } } } @@ -1977,28 +1897,28 @@ CALL [1] { } } } - LIST [67] { + LIST [55] { elements: { - COMPREHENSION [68] { - iter_var: @c:3 + COMPREHENSION [56] { + iter_var: @it:0:1 iter_range: { - IDENT [69] { - name: @index1 + IDENT [57] { + name: @index3 } } - accu_var: @x:3 + accu_var: @ac:0:1 accu_init: { - CONSTANT [70] { value: false } + CONSTANT [58] { value: false } } loop_condition: { - CALL [71] { + CALL [59] { function: @not_strictly_false args: { - CALL [72] { + CALL [60] { function: !_ args: { - IDENT [73] { - name: @x:3 + IDENT [61] { + name: @ac:0:1 } } } @@ -2006,13 +1926,13 @@ CALL [1] { } } loop_step: { - IDENT [74] { - name: @index9 + IDENT [62] { + name: @index5 } } result: { - IDENT [75] { - name: @x:3 + IDENT [63] { + name: @ac:0:1 } } } @@ -2020,8 +1940,8 @@ CALL [1] { } } } - IDENT [76] { - name: @index10 + IDENT [64] { + name: @index6 } } } @@ -2044,7 +1964,7 @@ CALL [1] { function: _>_ args: { IDENT [6] { - name: @c:0 + name: @it:0:0 } CONSTANT [7] { value: 0 } } @@ -2053,7 +1973,7 @@ CALL [1] { function: _||_ args: { IDENT [9] { - name: @x:0 + name: @ac:0:0 } IDENT [10] { name: @index1 @@ -2064,95 +1984,55 @@ CALL [1] { function: _>_ args: { IDENT [12] { - name: @c:1 + name: @it:0:0 } - CONSTANT [13] { value: 0 } + CONSTANT [13] { value: 1 } } } CALL [14] { function: _||_ args: { IDENT [15] { - name: @x:1 + name: @ac:0:0 } IDENT [16] { name: @index3 } } } - CALL [17] { - function: _>_ - args: { - IDENT [18] { - name: @c:2 - } - CONSTANT [19] { value: 1 } - } - } - CALL [20] { - function: _||_ - args: { - IDENT [21] { - name: @x:2 - } - IDENT [22] { - name: @index5 - } - } - } - LIST [23] { + LIST [17] { elements: { - CONSTANT [24] { value: 2 } - } - } - CALL [25] { - function: _>_ - args: { - IDENT [26] { - name: @c:3 - } - CONSTANT [27] { value: 1 } - } - } - CALL [28] { - function: _||_ - args: { - IDENT [29] { - name: @x:3 - } - IDENT [30] { - name: @index8 - } + CONSTANT [18] { value: 2 } } } } } - CALL [31] { + CALL [19] { function: _&&_ args: { - CALL [32] { + CALL [20] { function: _&&_ args: { - COMPREHENSION [33] { - iter_var: @c:0 + COMPREHENSION [21] { + iter_var: @it:0:0 iter_range: { - IDENT [34] { + IDENT [22] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [35] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [36] { + CALL [24] { function: @not_strictly_false args: { - CALL [37] { + CALL [25] { function: !_ args: { - IDENT [38] { - name: @x:0 + IDENT [26] { + name: @ac:0:0 } } } @@ -2160,36 +2040,36 @@ CALL [1] { } } loop_step: { - IDENT [39] { + IDENT [27] { name: @index2 } } result: { - IDENT [40] { - name: @x:0 + IDENT [28] { + name: @ac:0:0 } } } - COMPREHENSION [41] { - iter_var: @c:1 + COMPREHENSION [29] { + iter_var: @it:0:0 iter_range: { - IDENT [42] { + IDENT [30] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [43] { value: false } + CONSTANT [31] { value: false } } loop_condition: { - CALL [44] { + CALL [32] { function: @not_strictly_false args: { - CALL [45] { + CALL [33] { function: !_ args: { - IDENT [46] { - name: @x:1 + IDENT [34] { + name: @ac:0:0 } } } @@ -2197,41 +2077,41 @@ CALL [1] { } } loop_step: { - IDENT [47] { - name: @index4 + IDENT [35] { + name: @index2 } } result: { - IDENT [48] { - name: @x:1 + IDENT [36] { + name: @ac:0:0 } } } } } - CALL [49] { + CALL [37] { function: _&&_ args: { - COMPREHENSION [50] { - iter_var: @c:2 + COMPREHENSION [38] { + iter_var: @it:0:0 iter_range: { - IDENT [51] { + IDENT [39] { name: @index0 } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [52] { value: false } + CONSTANT [40] { value: false } } loop_condition: { - CALL [53] { + CALL [41] { function: @not_strictly_false args: { - CALL [54] { + CALL [42] { function: !_ args: { - IDENT [55] { - name: @x:2 + IDENT [43] { + name: @ac:0:0 } } } @@ -2239,36 +2119,36 @@ CALL [1] { } } loop_step: { - IDENT [56] { - name: @index6 + IDENT [44] { + name: @index4 } } result: { - IDENT [57] { - name: @x:2 + IDENT [45] { + name: @ac:0:0 } } } - COMPREHENSION [58] { - iter_var: @c:3 + COMPREHENSION [46] { + iter_var: @it:0:0 iter_range: { - IDENT [59] { - name: @index7 + IDENT [47] { + name: @index5 } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [60] { value: false } + CONSTANT [48] { value: false } } loop_condition: { - CALL [61] { + CALL [49] { function: @not_strictly_false args: { - CALL [62] { + CALL [50] { function: !_ args: { - IDENT [63] { - name: @x:3 + IDENT [51] { + name: @ac:0:0 } } } @@ -2276,13 +2156,13 @@ CALL [1] { } } loop_step: { - IDENT [64] { - name: @index9 + IDENT [52] { + name: @index4 } } result: { - IDENT [65] { - name: @x:3 + IDENT [53] { + name: @ac:0:0 } } } @@ -2318,7 +2198,7 @@ CALL [1] { function: _+_ args: { IDENT [12] { - name: @c:0 + name: @it:1:0 } CONSTANT [13] { value: 1 } } @@ -2334,7 +2214,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } IDENT [18] { name: @index3 @@ -2360,13 +2240,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [24] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [25] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [26] { elements: { @@ -2381,18 +2261,18 @@ CALL [1] { function: _+_ args: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } LIST [30] { elements: { COMPREHENSION [31] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [32] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [33] { elements: { @@ -2409,7 +2289,7 @@ CALL [1] { } result: { IDENT [36] { - name: @x:0 + name: @ac:1:0 } } } @@ -2420,7 +2300,7 @@ CALL [1] { } result: { IDENT [37] { - name: @x:1 + name: @ac:0:0 } } } @@ -2456,17 +2336,17 @@ CALL [1] { function: _==_ args: { IDENT [11] { - name: @c:0 + name: @it:1:0 } IDENT [12] { - name: @c:1 + name: @it:0:0 } } } LIST [13] { elements: { IDENT [14] { - name: @c:0 + name: @it:1:0 } } } @@ -2474,7 +2354,7 @@ CALL [1] { function: _+_ args: { IDENT [16] { - name: @x:0 + name: @ac:1:0 } IDENT [17] { name: @index3 @@ -2491,7 +2371,7 @@ CALL [1] { name: @index4 } IDENT [21] { - name: @x:0 + name: @ac:1:0 } } } @@ -2521,13 +2401,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [30] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [31] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [32] { elements: { @@ -2542,18 +2422,18 @@ CALL [1] { function: _+_ args: { IDENT [35] { - name: @x:1 + name: @ac:0:0 } LIST [36] { elements: { COMPREHENSION [37] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [38] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [39] { elements: { @@ -2570,7 +2450,7 @@ CALL [1] { } result: { IDENT [42] { - name: @x:0 + name: @ac:1:0 } } } @@ -2581,7 +2461,7 @@ CALL [1] { } result: { IDENT [43] { - name: @x:1 + name: @ac:0:0 } } } @@ -2611,7 +2491,7 @@ CALL [1] { function: _+_ args: { IDENT [8] { - name: @c:0 + name: @it:1:0 } CONSTANT [9] { value: 1 } } @@ -2627,96 +2507,69 @@ CALL [1] { function: _+_ args: { IDENT [13] { - name: @x:0 + name: @ac:1:0 } IDENT [14] { name: @index2 } } } - CALL [15] { - function: _+_ - args: { - IDENT [16] { - name: @c:2 - } - CONSTANT [17] { value: 1 } - } - } - LIST [18] { - elements: { - IDENT [19] { - name: @index4 - } - } - } - CALL [20] { - function: _+_ - args: { - IDENT [21] { - name: @x:2 - } - IDENT [22] { - name: @index5 - } - } - } } } - CALL [23] { + CALL [15] { function: _==_ args: { - COMPREHENSION [24] { - iter_var: @c:1 + COMPREHENSION [16] { + iter_var: @it:0:0 iter_range: { - IDENT [25] { + IDENT [17] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - LIST [26] { + LIST [18] { elements: { } } } loop_condition: { - CONSTANT [27] { value: true } + CONSTANT [19] { value: true } } loop_step: { - CALL [28] { + CALL [20] { function: _+_ args: { - IDENT [29] { - name: @x:1 + IDENT [21] { + name: @ac:0:0 } - LIST [30] { + LIST [22] { elements: { - COMPREHENSION [31] { - iter_var: @c:0 + COMPREHENSION [23] { + iter_var: @it:1:0 iter_range: { - IDENT [32] { + IDENT [24] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { - LIST [33] { + LIST [25] { elements: { } } } loop_condition: { - CONSTANT [34] { value: true } + CONSTANT [26] { value: true } } loop_step: { - IDENT [35] { + IDENT [27] { name: @index3 } } result: { - IDENT [36] { - name: @x:0 + IDENT [28] { + name: @ac:1:0 } } } @@ -2726,62 +2579,62 @@ CALL [1] { } } result: { - IDENT [37] { - name: @x:1 + IDENT [29] { + name: @ac:0:0 } } } - COMPREHENSION [38] { - iter_var: @c:3 + COMPREHENSION [30] { + iter_var: @it:0:0 iter_range: { - IDENT [39] { + IDENT [31] { name: @index0 } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [40] { + LIST [32] { elements: { } } } loop_condition: { - CONSTANT [41] { value: true } + CONSTANT [33] { value: true } } loop_step: { - CALL [42] { + CALL [34] { function: _+_ args: { - IDENT [43] { - name: @x:3 + IDENT [35] { + name: @ac:0:0 } - LIST [44] { + LIST [36] { elements: { - COMPREHENSION [45] { - iter_var: @c:2 + COMPREHENSION [37] { + iter_var: @it:1:0 iter_range: { - IDENT [46] { + IDENT [38] { name: @index0 } } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [47] { + LIST [39] { elements: { } } } loop_condition: { - CONSTANT [48] { value: true } + CONSTANT [40] { value: true } } loop_step: { - IDENT [49] { - name: @index6 + IDENT [41] { + name: @index3 } } result: { - IDENT [50] { - name: @x:2 + IDENT [42] { + name: @ac:1:0 } } } @@ -2791,8 +2644,8 @@ CALL [1] { } } result: { - IDENT [51] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -2989,7 +2842,7 @@ CALL [1] { function: _+_ args: { IDENT [15] { - name: @x:0 + name: @ac:1:0 } IDENT [16] { name: @index3 @@ -3012,13 +2865,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [21] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [22] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -3033,18 +2886,18 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { COMPREHENSION [28] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [29] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [30] { elements: { @@ -3061,7 +2914,7 @@ CALL [1] { } result: { IDENT [33] { - name: @x:0 + name: @ac:1:0 } } } @@ -3072,7 +2925,7 @@ CALL [1] { } result: { IDENT [34] { - name: @x:1 + name: @ac:0:0 } } } @@ -3132,7 +2985,7 @@ CALL [1] { function: _-_ args: { IDENT [16] { - name: @c:0 + name: @it:0:0 } CONSTANT [17] { value: 1 } } @@ -3150,7 +3003,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } IDENT [23] { name: @index5 @@ -3163,13 +3016,13 @@ CALL [1] { function: _||_ args: { COMPREHENSION [25] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { IDENT [26] { name: @index3 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [27] { value: false } } @@ -3181,7 +3034,7 @@ CALL [1] { function: !_ args: { IDENT [30] { - name: @x:0 + name: @ac:0:0 } } } @@ -3195,7 +3048,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:0 + name: @ac:0:0 } } } @@ -3218,10 +3071,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -3229,10 +3082,10 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } @@ -3263,7 +3116,7 @@ CALL [1] { function: _+_ args: { IDENT [18] { - name: @x:0 + name: @ac:1:0 } IDENT [19] { name: @index4 @@ -3291,7 +3144,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } IDENT [27] { name: @index7 @@ -3301,16 +3154,16 @@ CALL [1] { } } COMPREHENSION [28] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [29] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [30] { name: @index2 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [31] { elements: { @@ -3327,12 +3180,12 @@ CALL [1] { } result: { IDENT [34] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [35] { elements: { @@ -3349,7 +3202,7 @@ CALL [1] { } result: { IDENT [38] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline index 7a46177d8..28336f2e3 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline @@ -1252,123 +1252,89 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - CALL [7] { + CALL [3] { function: _||_ args: { - IDENT [8] { - name: @x:0 + IDENT [4] { + name: @ac:0:0 } - CALL [9] { + CALL [5] { function: _>_ args: { - IDENT [10] { - name: @c:0 + IDENT [6] { + name: @it:0:0 } - CONSTANT [11] { value: 0 } + CONSTANT [7] { value: 0 } } } } } - CALL [12] { + CALL [8] { function: _||_ args: { - IDENT [13] { - name: @x:1 + IDENT [9] { + name: @ac:0:0 } - CALL [14] { + CALL [10] { function: _>_ args: { - IDENT [15] { - name: @c:1 + IDENT [11] { + name: @it:0:0 } - CONSTANT [16] { value: 0 } + CONSTANT [12] { value: 1 } } } } } - CALL [17] { - function: _||_ - args: { - IDENT [18] { - name: @x:2 - } - CALL [19] { - function: _>_ - args: { - IDENT [20] { - name: @c:2 - } - CONSTANT [21] { value: 1 } - } - } + LIST [13] { + elements: { + CONSTANT [14] { value: 1 } } } - CALL [22] { - function: _||_ - args: { - IDENT [23] { - name: @x:3 - } - CALL [24] { - function: _>_ - args: { - IDENT [25] { - name: @c:3 - } - CONSTANT [26] { value: 1 } - } - } + LIST [15] { + elements: { + CONSTANT [16] { value: 2 } } } } } - CALL [27] { + CALL [17] { function: _==_ args: { - CALL [28] { + CALL [18] { function: _+_ args: { - CALL [29] { + CALL [19] { function: _+_ args: { - CALL [30] { + CALL [20] { function: _+_ args: { - CALL [31] { + CALL [21] { function: size args: { - LIST [32] { + LIST [22] { elements: { - COMPREHENSION [33] { - iter_var: @c:0 + COMPREHENSION [23] { + iter_var: @it:0:0 iter_range: { - IDENT [34] { - name: @index0 + IDENT [24] { + name: @index2 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [35] { value: false } + CONSTANT [25] { value: false } } loop_condition: { - CALL [36] { + CALL [26] { function: @not_strictly_false args: { - CALL [37] { + CALL [27] { function: !_ args: { - IDENT [38] { - name: @x:0 + IDENT [28] { + name: @ac:0:0 } } } @@ -1376,13 +1342,13 @@ CALL [1] { } } loop_step: { - IDENT [39] { - name: @index2 + IDENT [29] { + name: @index0 } } result: { - IDENT [40] { - name: @x:0 + IDENT [30] { + name: @ac:0:0 } } } @@ -1390,31 +1356,31 @@ CALL [1] { } } } - CALL [41] { + CALL [31] { function: size args: { - LIST [42] { + LIST [32] { elements: { - COMPREHENSION [43] { - iter_var: @c:1 + COMPREHENSION [33] { + iter_var: @it:0:0 iter_range: { - IDENT [44] { - name: @index0 + IDENT [34] { + name: @index2 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [45] { value: false } + CONSTANT [35] { value: false } } loop_condition: { - CALL [46] { + CALL [36] { function: @not_strictly_false args: { - CALL [47] { + CALL [37] { function: !_ args: { - IDENT [48] { - name: @x:1 + IDENT [38] { + name: @ac:0:0 } } } @@ -1422,13 +1388,13 @@ CALL [1] { } } loop_step: { - IDENT [49] { - name: @index3 + IDENT [39] { + name: @index0 } } result: { - IDENT [50] { - name: @x:1 + IDENT [40] { + name: @ac:0:0 } } } @@ -1438,31 +1404,31 @@ CALL [1] { } } } - CALL [51] { + CALL [41] { function: size args: { - LIST [52] { + LIST [42] { elements: { - COMPREHENSION [53] { - iter_var: @c:2 + COMPREHENSION [43] { + iter_var: @it:0:0 iter_range: { - IDENT [54] { - name: @index1 + IDENT [44] { + name: @index3 } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [55] { value: false } + CONSTANT [45] { value: false } } loop_condition: { - CALL [56] { + CALL [46] { function: @not_strictly_false args: { - CALL [57] { + CALL [47] { function: !_ args: { - IDENT [58] { - name: @x:2 + IDENT [48] { + name: @ac:0:0 } } } @@ -1470,13 +1436,13 @@ CALL [1] { } } loop_step: { - IDENT [59] { - name: @index4 + IDENT [49] { + name: @index1 } } result: { - IDENT [60] { - name: @x:2 + IDENT [50] { + name: @ac:0:0 } } } @@ -1486,31 +1452,31 @@ CALL [1] { } } } - CALL [61] { + CALL [51] { function: size args: { - LIST [62] { + LIST [52] { elements: { - COMPREHENSION [63] { - iter_var: @c:3 + COMPREHENSION [53] { + iter_var: @it:0:0 iter_range: { - IDENT [64] { - name: @index1 + IDENT [54] { + name: @index3 } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [65] { value: false } + CONSTANT [55] { value: false } } loop_condition: { - CALL [66] { + CALL [56] { function: @not_strictly_false args: { - CALL [67] { + CALL [57] { function: !_ args: { - IDENT [68] { - name: @x:3 + IDENT [58] { + name: @ac:0:0 } } } @@ -1518,13 +1484,13 @@ CALL [1] { } } loop_step: { - IDENT [69] { - name: @index5 + IDENT [59] { + name: @index1 } } result: { - IDENT [70] { - name: @x:3 + IDENT [60] { + name: @ac:0:0 } } } @@ -1534,7 +1500,7 @@ CALL [1] { } } } - CONSTANT [71] { value: 4 } + CONSTANT [61] { value: 4 } } } } @@ -1547,128 +1513,94 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - CALL [7] { + CALL [3] { function: _||_ args: { - IDENT [8] { - name: @x:0 + IDENT [4] { + name: @ac:0:0 } - CALL [9] { + CALL [5] { function: _>_ args: { - IDENT [10] { - name: @c:0 + IDENT [6] { + name: @it:0:0 } - CONSTANT [11] { value: 0 } + CONSTANT [7] { value: 0 } } } } } - CALL [12] { + CALL [8] { function: _||_ args: { - IDENT [13] { - name: @x:1 + IDENT [9] { + name: @ac:0:1 } - CALL [14] { - function: _>_ + CALL [10] { + function: _==_ args: { - IDENT [15] { - name: @c:1 + IDENT [11] { + name: @it:0:1 } - CONSTANT [16] { value: 0 } + CONSTANT [12] { value: "a" } } } } } - CALL [17] { - function: _||_ - args: { - IDENT [18] { - name: @x:2 - } - CALL [19] { - function: _==_ - args: { - IDENT [20] { - name: @c:2 - } - CONSTANT [21] { value: "a" } - } - } + LIST [13] { + elements: { + CONSTANT [14] { value: 1 } } } - CALL [22] { - function: _||_ - args: { - IDENT [23] { - name: @x:3 - } - CALL [24] { - function: _==_ - args: { - IDENT [25] { - name: @c:3 - } - CONSTANT [26] { value: "a" } - } - } + LIST [15] { + elements: { + CONSTANT [16] { value: "a" } } } - LIST [27] { + LIST [17] { elements: { - CONSTANT [28] { value: true } - CONSTANT [29] { value: true } - CONSTANT [30] { value: true } - CONSTANT [31] { value: true } + CONSTANT [18] { value: true } + CONSTANT [19] { value: true } + CONSTANT [20] { value: true } + CONSTANT [21] { value: true } } } } } - CALL [32] { + CALL [22] { function: _==_ args: { - CALL [33] { + CALL [23] { function: _+_ args: { - CALL [34] { + CALL [24] { function: _+_ args: { - CALL [35] { + CALL [25] { function: _+_ args: { - LIST [36] { + LIST [26] { elements: { - COMPREHENSION [37] { - iter_var: @c:0 + COMPREHENSION [27] { + iter_var: @it:0:0 iter_range: { - IDENT [38] { - name: @index0 + IDENT [28] { + name: @index2 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [39] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [40] { + CALL [30] { function: @not_strictly_false args: { - CALL [41] { + CALL [31] { function: !_ args: { - IDENT [42] { - name: @x:0 + IDENT [32] { + name: @ac:0:0 } } } @@ -1676,40 +1608,40 @@ CALL [1] { } } loop_step: { - IDENT [43] { - name: @index2 + IDENT [33] { + name: @index0 } } result: { - IDENT [44] { - name: @x:0 + IDENT [34] { + name: @ac:0:0 } } } } } - LIST [45] { + LIST [35] { elements: { - COMPREHENSION [46] { - iter_var: @c:1 + COMPREHENSION [36] { + iter_var: @it:0:0 iter_range: { - IDENT [47] { - name: @index0 + IDENT [37] { + name: @index2 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [48] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [49] { + CALL [39] { function: @not_strictly_false args: { - CALL [50] { + CALL [40] { function: !_ args: { - IDENT [51] { - name: @x:1 + IDENT [41] { + name: @ac:0:0 } } } @@ -1717,13 +1649,13 @@ CALL [1] { } } loop_step: { - IDENT [52] { - name: @index3 + IDENT [42] { + name: @index0 } } result: { - IDENT [53] { - name: @x:1 + IDENT [43] { + name: @ac:0:0 } } } @@ -1731,28 +1663,28 @@ CALL [1] { } } } - LIST [54] { + LIST [44] { elements: { - COMPREHENSION [55] { - iter_var: @c:2 + COMPREHENSION [45] { + iter_var: @it:0:1 iter_range: { - IDENT [56] { - name: @index1 + IDENT [46] { + name: @index3 } } - accu_var: @x:2 + accu_var: @ac:0:1 accu_init: { - CONSTANT [57] { value: false } + CONSTANT [47] { value: false } } loop_condition: { - CALL [58] { + CALL [48] { function: @not_strictly_false args: { - CALL [59] { + CALL [49] { function: !_ args: { - IDENT [60] { - name: @x:2 + IDENT [50] { + name: @ac:0:1 } } } @@ -1760,13 +1692,13 @@ CALL [1] { } } loop_step: { - IDENT [61] { - name: @index4 + IDENT [51] { + name: @index1 } } result: { - IDENT [62] { - name: @x:2 + IDENT [52] { + name: @ac:0:1 } } } @@ -1774,28 +1706,28 @@ CALL [1] { } } } - LIST [63] { + LIST [53] { elements: { - COMPREHENSION [64] { - iter_var: @c:3 + COMPREHENSION [54] { + iter_var: @it:0:1 iter_range: { - IDENT [65] { - name: @index1 + IDENT [55] { + name: @index3 } } - accu_var: @x:3 + accu_var: @ac:0:1 accu_init: { - CONSTANT [66] { value: false } + CONSTANT [56] { value: false } } loop_condition: { - CALL [67] { + CALL [57] { function: @not_strictly_false args: { - CALL [68] { + CALL [58] { function: !_ args: { - IDENT [69] { - name: @x:3 + IDENT [59] { + name: @ac:0:1 } } } @@ -1803,13 +1735,13 @@ CALL [1] { } } loop_step: { - IDENT [70] { - name: @index5 + IDENT [60] { + name: @index1 } } result: { - IDENT [71] { - name: @x:3 + IDENT [61] { + name: @ac:0:1 } } } @@ -1817,8 +1749,8 @@ CALL [1] { } } } - IDENT [72] { - name: @index6 + IDENT [62] { + name: @index4 } } } @@ -1832,112 +1764,78 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - CALL [5] { - function: _||_ - args: { - IDENT [6] { - name: @x:0 - } - CALL [7] { - function: _>_ - args: { - IDENT [8] { - name: @c:0 - } - CONSTANT [9] { value: 0 } - } - } - } - } - CALL [10] { + CALL [3] { function: _||_ args: { - IDENT [11] { - name: @x:1 + IDENT [4] { + name: @ac:0:0 } - CALL [12] { + CALL [5] { function: _>_ args: { - IDENT [13] { - name: @c:1 + IDENT [6] { + name: @it:0:0 } - CONSTANT [14] { value: 0 } + CONSTANT [7] { value: 0 } } } } } - CALL [15] { + CALL [8] { function: _||_ args: { - IDENT [16] { - name: @x:2 + IDENT [9] { + name: @ac:0:0 } - CALL [17] { + CALL [10] { function: _>_ args: { - IDENT [18] { - name: @c:2 + IDENT [11] { + name: @it:0:0 } - CONSTANT [19] { value: 1 } + CONSTANT [12] { value: 1 } } } } } - CALL [20] { - function: _||_ - args: { - IDENT [21] { - name: @x:3 - } - CALL [22] { - function: _>_ - args: { - IDENT [23] { - name: @c:3 - } - CONSTANT [24] { value: 1 } - } - } + LIST [13] { + elements: { + CONSTANT [14] { value: 1 } } } - LIST [25] { + LIST [15] { elements: { - CONSTANT [26] { value: 2 } + CONSTANT [16] { value: 2 } } } } } - CALL [27] { + CALL [17] { function: _&&_ args: { - CALL [28] { + CALL [18] { function: _&&_ args: { - COMPREHENSION [29] { - iter_var: @c:0 + COMPREHENSION [19] { + iter_var: @it:0:0 iter_range: { - IDENT [30] { - name: @index0 + IDENT [20] { + name: @index2 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [31] { value: false } + CONSTANT [21] { value: false } } loop_condition: { - CALL [32] { + CALL [22] { function: @not_strictly_false args: { - CALL [33] { + CALL [23] { function: !_ args: { - IDENT [34] { - name: @x:0 + IDENT [24] { + name: @ac:0:0 } } } @@ -1945,36 +1843,36 @@ CALL [1] { } } loop_step: { - IDENT [35] { - name: @index1 + IDENT [25] { + name: @index0 } } result: { - IDENT [36] { - name: @x:0 + IDENT [26] { + name: @ac:0:0 } } } - COMPREHENSION [37] { - iter_var: @c:1 + COMPREHENSION [27] { + iter_var: @it:0:0 iter_range: { - IDENT [38] { - name: @index0 + IDENT [28] { + name: @index2 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [39] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [40] { + CALL [30] { function: @not_strictly_false args: { - CALL [41] { + CALL [31] { function: !_ args: { - IDENT [42] { - name: @x:1 + IDENT [32] { + name: @ac:0:0 } } } @@ -1982,41 +1880,41 @@ CALL [1] { } } loop_step: { - IDENT [43] { - name: @index2 + IDENT [33] { + name: @index0 } } result: { - IDENT [44] { - name: @x:1 + IDENT [34] { + name: @ac:0:0 } } } } } - CALL [45] { + CALL [35] { function: _&&_ args: { - COMPREHENSION [46] { - iter_var: @c:2 + COMPREHENSION [36] { + iter_var: @it:0:0 iter_range: { - IDENT [47] { - name: @index0 + IDENT [37] { + name: @index2 } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [48] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [49] { + CALL [39] { function: @not_strictly_false args: { - CALL [50] { + CALL [40] { function: !_ args: { - IDENT [51] { - name: @x:2 + IDENT [41] { + name: @ac:0:0 } } } @@ -2024,36 +1922,36 @@ CALL [1] { } } loop_step: { - IDENT [52] { - name: @index3 + IDENT [42] { + name: @index1 } } result: { - IDENT [53] { - name: @x:2 + IDENT [43] { + name: @ac:0:0 } } } - COMPREHENSION [54] { - iter_var: @c:3 + COMPREHENSION [44] { + iter_var: @it:0:0 iter_range: { - IDENT [55] { - name: @index5 + IDENT [45] { + name: @index3 } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [56] { value: false } + CONSTANT [46] { value: false } } loop_condition: { - CALL [57] { + CALL [47] { function: @not_strictly_false args: { - CALL [58] { + CALL [48] { function: !_ args: { - IDENT [59] { - name: @x:3 + IDENT [49] { + name: @ac:0:0 } } } @@ -2061,13 +1959,13 @@ CALL [1] { } } loop_step: { - IDENT [60] { - name: @index4 + IDENT [50] { + name: @index1 } } result: { - IDENT [61] { - name: @x:3 + IDENT [51] { + name: @ac:0:0 } } } @@ -2105,7 +2003,7 @@ CALL [1] { function: _+_ args: { IDENT [13] { - name: @c:0 + name: @it:1:0 } CONSTANT [14] { value: 1 } } @@ -2113,13 +2011,13 @@ CALL [1] { } } COMPREHENSION [15] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [16] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [17] { elements: { @@ -2134,7 +2032,7 @@ CALL [1] { function: _+_ args: { IDENT [20] { - name: @x:0 + name: @ac:1:0 } IDENT [21] { name: @index2 @@ -2144,7 +2042,7 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -2152,7 +2050,7 @@ CALL [1] { function: _+_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:0 } LIST [25] { elements: { @@ -2164,13 +2062,13 @@ CALL [1] { } } COMPREHENSION [27] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [28] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [29] { elements: { @@ -2187,7 +2085,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } } } @@ -2228,12 +2126,12 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @x:0 + name: @ac:1:0 } LIST [5] { elements: { IDENT [6] { - name: @c:0 + name: @it:1:0 } } } @@ -2246,10 +2144,10 @@ CALL [1] { function: _==_ args: { IDENT [9] { - name: @c:0 + name: @it:1:0 } IDENT [10] { - name: @c:1 + name: @it:0:0 } } } @@ -2257,12 +2155,12 @@ CALL [1] { name: @index0 } IDENT [12] { - name: @x:0 + name: @ac:1:0 } } } COMPREHENSION [13] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [14] { elements: { @@ -2272,7 +2170,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [18] { elements: { @@ -2289,7 +2187,7 @@ CALL [1] { } result: { IDENT [21] { - name: @x:0 + name: @ac:1:0 } } } @@ -2297,7 +2195,7 @@ CALL [1] { function: _+_ args: { IDENT [23] { - name: @x:1 + name: @ac:0:0 } LIST [24] { elements: { @@ -2309,7 +2207,7 @@ CALL [1] { } } COMPREHENSION [26] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [27] { elements: { @@ -2318,7 +2216,7 @@ CALL [1] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [30] { elements: { @@ -2335,7 +2233,7 @@ CALL [1] { } result: { IDENT [33] { - name: @x:1 + name: @ac:0:0 } } } @@ -2378,205 +2276,114 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - LIST [7] { - elements: { - CALL [8] { - function: _+_ - args: { - IDENT [9] { - name: @c:0 - } - CONSTANT [10] { value: 1 } - } - } - } - } - COMPREHENSION [11] { - iter_var: @c:0 - iter_range: { - IDENT [12] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [13] { - elements: { - } - } - } - loop_condition: { - CONSTANT [14] { value: true } - } - loop_step: { - CALL [15] { + CALL [4] { function: _+_ args: { - IDENT [16] { - name: @x:0 - } - IDENT [17] { - name: @index1 - } - } - } - } - result: { - IDENT [18] { - name: @x:0 - } - } - } - CALL [19] { - function: _+_ - args: { - IDENT [20] { - name: @x:1 - } - LIST [21] { - elements: { - IDENT [22] { - name: @index2 + IDENT [5] { + name: @it:1:0 } + CONSTANT [6] { value: 1 } } } } } - COMPREHENSION [23] { - iter_var: @c:1 + COMPREHENSION [7] { + iter_var: @it:1:0 iter_range: { - IDENT [24] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [25] { + LIST [8] { elements: { + CONSTANT [9] { value: 1 } + CONSTANT [10] { value: 2 } + CONSTANT [11] { value: 3 } } } } - loop_condition: { - CONSTANT [26] { value: true } - } - loop_step: { - IDENT [27] { - name: @index3 - } - } - result: { - IDENT [28] { - name: @x:1 - } - } - } - LIST [29] { - elements: { - CALL [30] { - function: _+_ - args: { - IDENT [31] { - name: @c:2 - } - CONSTANT [32] { value: 1 } - } - } - } - } - COMPREHENSION [33] { - iter_var: @c:2 - iter_range: { - IDENT [34] { - name: @index0 - } - } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [35] { + LIST [12] { elements: { } } } loop_condition: { - CONSTANT [36] { value: true } + CONSTANT [13] { value: true } } loop_step: { - CALL [37] { + CALL [14] { function: _+_ args: { - IDENT [38] { - name: @x:2 + IDENT [15] { + name: @ac:1:0 } - IDENT [39] { - name: @index5 + IDENT [16] { + name: @index0 } } } } result: { - IDENT [40] { - name: @x:2 + IDENT [17] { + name: @ac:1:0 } } } - CALL [41] { + CALL [18] { function: _+_ args: { - IDENT [42] { - name: @x:3 + IDENT [19] { + name: @ac:0:0 } - LIST [43] { + LIST [20] { elements: { - IDENT [44] { - name: @index6 + IDENT [21] { + name: @index1 } } } } } - COMPREHENSION [45] { - iter_var: @c:3 + COMPREHENSION [22] { + iter_var: @it:0:0 iter_range: { - IDENT [46] { - name: @index0 + LIST [23] { + elements: { + CONSTANT [24] { value: 1 } + CONSTANT [25] { value: 2 } + CONSTANT [26] { value: 3 } + } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [47] { + LIST [27] { elements: { } } } loop_condition: { - CONSTANT [48] { value: true } + CONSTANT [28] { value: true } } loop_step: { - IDENT [49] { - name: @index7 + IDENT [29] { + name: @index2 } } result: { - IDENT [50] { - name: @x:3 + IDENT [30] { + name: @ac:0:0 } } } } } - CALL [51] { + CALL [31] { function: _==_ args: { - IDENT [52] { - name: @index4 + IDENT [32] { + name: @index3 } - IDENT [53] { - name: @index8 + IDENT [33] { + name: @index3 } } } @@ -2763,13 +2570,13 @@ CALL [1] { } } COMPREHENSION [17] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [18] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [19] { elements: { @@ -2784,7 +2591,7 @@ CALL [1] { function: _+_ args: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } IDENT [23] { name: @index2 @@ -2794,7 +2601,7 @@ CALL [1] { } result: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } } } @@ -2802,7 +2609,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2814,13 +2621,13 @@ CALL [1] { } } COMPREHENSION [29] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [30] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [31] { elements: { @@ -2837,7 +2644,7 @@ CALL [1] { } result: { IDENT [34] { - name: @x:1 + name: @ac:0:0 } } } @@ -2911,7 +2718,7 @@ CALL [1] { function: _-_ args: { IDENT [16] { - name: @c:0 + name: @it:0:0 } CONSTANT [17] { value: 1 } } @@ -2930,7 +2737,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } IDENT [23] { name: @index2 @@ -2943,13 +2750,13 @@ CALL [1] { function: _||_ args: { COMPREHENSION [25] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { IDENT [26] { name: @index3 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [27] { value: false } } @@ -2961,7 +2768,7 @@ CALL [1] { function: !_ args: { IDENT [30] { - name: @x:0 + name: @ac:0:0 } } } @@ -2975,7 +2782,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:0 + name: @ac:0:0 } } } @@ -2998,10 +2805,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -3009,10 +2816,10 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } @@ -3031,7 +2838,7 @@ CALL [1] { } } COMPREHENSION [13] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [14] { elements: { @@ -3040,7 +2847,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [17] { elements: { @@ -3055,7 +2862,7 @@ CALL [1] { function: _+_ args: { IDENT [20] { - name: @x:0 + name: @ac:1:0 } IDENT [21] { name: @index2 @@ -3065,7 +2872,7 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -3086,13 +2893,13 @@ CALL [1] { } } COMPREHENSION [27] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [28] { name: @index3 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [29] { elements: { @@ -3107,7 +2914,7 @@ CALL [1] { function: _+_ args: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } IDENT [33] { name: @index4 @@ -3117,7 +2924,7 @@ CALL [1] { } result: { IDENT [34] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline index 6ecc6d04a..4018942c4 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline @@ -1199,36 +1199,28 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - COMPREHENSION [7] { - iter_var: @c:0 + COMPREHENSION [3] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [6] { value: false } } loop_condition: { - CALL [10] { + CALL [7] { function: @not_strictly_false args: { - CALL [11] { + CALL [8] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [9] { + name: @ac:0:0 } } } @@ -1236,50 +1228,52 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [10] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [11] { + name: @ac:0:0 } - CALL [15] { + CALL [12] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [13] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [14] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [15] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + COMPREHENSION [16] { + iter_var: @it:0:0 iter_range: { - IDENT [20] { - name: @index0 + LIST [17] { + elements: { + CONSTANT [18] { value: 2 } + } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [21] { value: false } + CONSTANT [19] { value: false } } loop_condition: { - CALL [22] { + CALL [20] { function: @not_strictly_false args: { - CALL [23] { + CALL [21] { function: !_ args: { - IDENT [24] { - name: @x:1 + IDENT [22] { + name: @ac:0:0 } } } @@ -1287,210 +1281,90 @@ CALL [1] { } } loop_step: { - CALL [25] { + CALL [23] { function: _||_ args: { - IDENT [26] { - name: @x:1 + IDENT [24] { + name: @ac:0:0 } - CALL [27] { + CALL [25] { function: _>_ args: { - IDENT [28] { - name: @c:1 + IDENT [26] { + name: @it:0:0 } - CONSTANT [29] { value: 0 } + CONSTANT [27] { value: 1 } } } } } } result: { - IDENT [30] { - name: @x:1 + IDENT [28] { + name: @ac:0:0 } } } - CALL [31] { - function: _+_ + CALL [29] { + function: size args: { - CALL [32] { - function: size - args: { - LIST [33] { - elements: { - IDENT [34] { - name: @index2 - } - } - } - } - } - CALL [35] { - function: size - args: { - LIST [36] { - elements: { - IDENT [37] { - name: @index3 - } - } + LIST [30] { + elements: { + IDENT [31] { + name: @index0 } } } } } - COMPREHENSION [38] { - iter_var: @c:2 - iter_range: { - IDENT [39] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [40] { value: false } - } - loop_condition: { - CALL [41] { - function: @not_strictly_false - args: { - CALL [42] { - function: !_ - args: { - IDENT [43] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [44] { - function: _||_ - args: { - IDENT [45] { - name: @x:2 - } - CALL [46] { - function: _>_ - args: { - IDENT [47] { - name: @c:2 - } - CONSTANT [48] { value: 1 } - } + CALL [32] { + function: size + args: { + LIST [33] { + elements: { + IDENT [34] { + name: @index1 } } } } - result: { - IDENT [49] { - name: @x:2 - } - } } - CALL [50] { + CALL [35] { function: _+_ args: { - IDENT [51] { - name: @index4 - } - CALL [52] { - function: size - args: { - LIST [53] { - elements: { - IDENT [54] { - name: @index5 - } - } - } - } - } - } - } - COMPREHENSION [55] { - iter_var: @c:3 - iter_range: { - IDENT [56] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [57] { value: false } - } - loop_condition: { - CALL [58] { - function: @not_strictly_false + CALL [36] { + function: _+_ args: { - CALL [59] { - function: !_ + CALL [37] { + function: _+_ args: { - IDENT [60] { - name: @x:3 + IDENT [38] { + name: @index2 } - } - } - } - } - } - loop_step: { - CALL [61] { - function: _||_ - args: { - IDENT [62] { - name: @x:3 - } - CALL [63] { - function: _>_ - args: { - IDENT [64] { - name: @c:3 + IDENT [39] { + name: @index2 } - CONSTANT [65] { value: 1 } } } - } - } - } - result: { - IDENT [66] { - name: @x:3 - } - } - } - CALL [67] { - function: _+_ - args: { - IDENT [68] { - name: @index6 - } - CALL [69] { - function: size - args: { - LIST [70] { - elements: { - IDENT [71] { - name: @index7 - } - } + IDENT [40] { + name: @index3 } } } + IDENT [41] { + name: @index3 + } } } } } - CALL [72] { + CALL [42] { function: _==_ args: { - IDENT [73] { - name: @index8 + IDENT [43] { + name: @index4 } - CONSTANT [74] { value: 4 } + CONSTANT [44] { value: 4 } } } } @@ -1503,36 +1377,28 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - COMPREHENSION [7] { - iter_var: @c:0 + COMPREHENSION [3] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [6] { value: false } } loop_condition: { - CALL [10] { + CALL [7] { function: @not_strictly_false args: { - CALL [11] { + CALL [8] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [9] { + name: @ac:0:0 } } } @@ -1540,50 +1406,52 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [10] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [11] { + name: @ac:0:0 } - CALL [15] { + CALL [12] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [13] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [14] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [15] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + COMPREHENSION [16] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [17] { + elements: { + CONSTANT [18] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { - CONSTANT [21] { value: false } + CONSTANT [19] { value: false } } loop_condition: { - CALL [22] { + CALL [20] { function: @not_strictly_false args: { - CALL [23] { + CALL [21] { function: !_ args: { - IDENT [24] { - name: @x:1 + IDENT [22] { + name: @ac:0:1 } } } @@ -1591,189 +1459,85 @@ CALL [1] { } } loop_step: { - CALL [25] { + CALL [23] { function: _||_ args: { - IDENT [26] { - name: @x:1 + IDENT [24] { + name: @ac:0:1 } - CALL [27] { - function: _>_ + CALL [25] { + function: _==_ args: { - IDENT [28] { - name: @c:1 + IDENT [26] { + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [27] { value: "a" } } } } } } result: { + IDENT [28] { + name: @ac:0:1 + } + } + } + LIST [29] { + elements: { IDENT [30] { - name: @x:1 + name: @index0 } } } - COMPREHENSION [31] { - iter_var: @c:2 - iter_range: { + LIST [31] { + elements: { IDENT [32] { name: @index1 } } - accu_var: @x:2 - accu_init: { - CONSTANT [33] { value: false } - } - loop_condition: { - CALL [34] { - function: @not_strictly_false - args: { - CALL [35] { - function: !_ - args: { - IDENT [36] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [37] { - function: _||_ - args: { - IDENT [38] { - name: @x:2 - } - CALL [39] { - function: _==_ - args: { - IDENT [40] { - name: @c:2 - } - CONSTANT [41] { value: "a" } - } - } - } - } - } - result: { - IDENT [42] { - name: @x:2 - } - } } - CALL [43] { + CALL [33] { function: _+_ args: { - CALL [44] { + CALL [34] { function: _+_ args: { - LIST [45] { - elements: { - IDENT [46] { - name: @index2 - } - } - } - LIST [47] { - elements: { - IDENT [48] { - name: @index3 - } - } - } - } - } - LIST [49] { - elements: { - IDENT [50] { - name: @index4 - } - } - } - } - } - COMPREHENSION [51] { - iter_var: @c:3 - iter_range: { - IDENT [52] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [53] { value: false } - } - loop_condition: { - CALL [54] { - function: @not_strictly_false - args: { - CALL [55] { - function: !_ - args: { - IDENT [56] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [57] { - function: _||_ - args: { - IDENT [58] { - name: @x:3 - } - CALL [59] { - function: _==_ + CALL [35] { + function: _+_ args: { - IDENT [60] { - name: @c:3 + IDENT [36] { + name: @index2 + } + IDENT [37] { + name: @index2 } - CONSTANT [61] { value: "a" } } } + IDENT [38] { + name: @index3 + } } } - } - result: { - IDENT [62] { - name: @x:3 + IDENT [39] { + name: @index3 } } } } } - CALL [63] { + CALL [40] { function: _==_ args: { - CALL [64] { - function: _+_ - args: { - IDENT [65] { - name: @index5 - } - LIST [66] { - elements: { - IDENT [67] { - name: @index6 - } - } - } - } + IDENT [41] { + name: @index4 } - LIST [68] { + LIST [42] { elements: { - CONSTANT [69] { value: true } - CONSTANT [70] { value: true } - CONSTANT [71] { value: true } - CONSTANT [72] { value: true } + CONSTANT [43] { value: true } + CONSTANT [44] { value: true } + CONSTANT [45] { value: true } + CONSTANT [46] { value: true } } } } @@ -1788,31 +1552,28 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - COMPREHENSION [5] { - iter_var: @c:0 + COMPREHENSION [3] { + iter_var: @it:0:0 iter_range: { - IDENT [6] { - name: @index0 + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [7] { value: false } + CONSTANT [6] { value: false } } loop_condition: { - CALL [8] { + CALL [7] { function: @not_strictly_false args: { - CALL [9] { + CALL [8] { function: !_ args: { - IDENT [10] { - name: @x:0 + IDENT [9] { + name: @ac:0:0 } } } @@ -1820,101 +1581,69 @@ CALL [1] { } } loop_step: { - CALL [11] { + CALL [10] { function: _||_ args: { - IDENT [12] { - name: @x:0 + IDENT [11] { + name: @ac:0:0 } - CALL [13] { + CALL [12] { function: _>_ args: { - IDENT [14] { - name: @c:0 + IDENT [13] { + name: @it:0:0 } - CONSTANT [15] { value: 0 } + CONSTANT [14] { value: 0 } } } } } } result: { - IDENT [16] { - name: @x:0 + IDENT [15] { + name: @ac:0:0 } } } - COMPREHENSION [17] { - iter_var: @c:1 - iter_range: { - IDENT [18] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [19] { value: false } - } - loop_condition: { - CALL [20] { - function: @not_strictly_false - args: { - CALL [21] { - function: !_ - args: { - IDENT [22] { - name: @x:1 - } - } - } - } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 } - } - loop_step: { - CALL [23] { - function: _||_ + CALL [18] { + function: _>_ args: { - IDENT [24] { - name: @x:1 - } - CALL [25] { - function: _>_ - args: { - IDENT [26] { - name: @c:1 - } - CONSTANT [27] { value: 0 } - } + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } - result: { - IDENT [28] { - name: @x:1 - } - } } - COMPREHENSION [29] { - iter_var: @c:2 + COMPREHENSION [21] { + iter_var: @it:0:0 iter_range: { - IDENT [30] { - name: @index0 + LIST [22] { + elements: { + CONSTANT [23] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [31] { value: false } + CONSTANT [24] { value: false } } loop_condition: { - CALL [32] { + CALL [25] { function: @not_strictly_false args: { - CALL [33] { + CALL [26] { function: !_ args: { - IDENT [34] { - name: @x:2 + IDENT [27] { + name: @ac:0:0 } } } @@ -1922,52 +1651,38 @@ CALL [1] { } } loop_step: { - CALL [35] { - function: _||_ - args: { - IDENT [36] { - name: @x:2 - } - CALL [37] { - function: _>_ - args: { - IDENT [38] { - name: @c:2 - } - CONSTANT [39] { value: 1 } - } - } - } + IDENT [28] { + name: @index1 } } result: { - IDENT [40] { - name: @x:2 + IDENT [29] { + name: @ac:0:0 } } } - COMPREHENSION [41] { - iter_var: @c:3 + COMPREHENSION [30] { + iter_var: @it:0:0 iter_range: { - LIST [42] { + LIST [31] { elements: { - CONSTANT [43] { value: 2 } + CONSTANT [32] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [44] { value: false } + CONSTANT [33] { value: false } } loop_condition: { - CALL [45] { + CALL [34] { function: @not_strictly_false args: { - CALL [46] { + CALL [35] { function: !_ args: { - IDENT [47] { - name: @x:3 + IDENT [36] { + name: @ac:0:0 } } } @@ -1975,54 +1690,40 @@ CALL [1] { } } loop_step: { - CALL [48] { - function: _||_ - args: { - IDENT [49] { - name: @x:3 - } - CALL [50] { - function: _>_ - args: { - IDENT [51] { - name: @c:3 - } - CONSTANT [52] { value: 1 } - } - } - } + IDENT [37] { + name: @index1 } } result: { - IDENT [53] { - name: @x:3 + IDENT [38] { + name: @ac:0:0 } } } } } - CALL [54] { + CALL [39] { function: _&&_ args: { - CALL [55] { + CALL [40] { function: _&&_ args: { - IDENT [56] { - name: @index1 + IDENT [41] { + name: @index0 } - IDENT [57] { - name: @index2 + IDENT [42] { + name: @index0 } } } - CALL [58] { + CALL [43] { function: _&&_ args: { - IDENT [59] { - name: @index3 + IDENT [44] { + name: @index2 } - IDENT [60] { - name: @index4 + IDENT [45] { + name: @index3 } } } @@ -2056,7 +1757,7 @@ CALL [1] { function: _+_ args: { IDENT [12] { - name: @x:0 + name: @ac:1:0 } LIST [13] { elements: { @@ -2064,7 +1765,7 @@ CALL [1] { function: _+_ args: { IDENT [15] { - name: @c:0 + name: @it:1:0 } CONSTANT [16] { value: 1 } } @@ -2076,13 +1777,13 @@ CALL [1] { LIST [17] { elements: { COMPREHENSION [18] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [19] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [20] { elements: { @@ -2099,7 +1800,7 @@ CALL [1] { } result: { IDENT [23] { - name: @x:0 + name: @ac:1:0 } } } @@ -2111,13 +1812,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [25] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [26] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [27] { elements: { @@ -2132,7 +1833,7 @@ CALL [1] { function: _+_ args: { IDENT [30] { - name: @x:1 + name: @ac:0:0 } IDENT [31] { name: @index3 @@ -2142,7 +1843,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } } } @@ -2178,10 +1879,10 @@ CALL [1] { function: _==_ args: { IDENT [5] { - name: @c:0 + name: @it:1:0 } IDENT [6] { - name: @c:1 + name: @it:0:0 } } } @@ -2189,26 +1890,26 @@ CALL [1] { function: _+_ args: { IDENT [8] { - name: @x:0 + name: @ac:1:0 } LIST [9] { elements: { IDENT [10] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [11] { - name: @x:0 + name: @ac:1:0 } } } LIST [12] { elements: { COMPREHENSION [13] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [14] { elements: { @@ -2218,7 +1919,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [18] { elements: { @@ -2235,7 +1936,7 @@ CALL [1] { } result: { IDENT [21] { - name: @x:0 + name: @ac:1:0 } } } @@ -2247,7 +1948,7 @@ CALL [1] { function: _==_ args: { COMPREHENSION [23] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [24] { elements: { @@ -2256,7 +1957,7 @@ CALL [1] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [27] { elements: { @@ -2271,7 +1972,7 @@ CALL [1] { function: _+_ args: { IDENT [30] { - name: @x:1 + name: @ac:0:0 } IDENT [31] { name: @index1 @@ -2281,7 +1982,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } } } @@ -2311,198 +2012,116 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - CALL [7] { + CALL [3] { function: _+_ args: { - IDENT [8] { - name: @x:0 + IDENT [4] { + name: @ac:1:0 } - LIST [9] { + LIST [5] { elements: { - CALL [10] { + CALL [6] { function: _+_ args: { - IDENT [11] { - name: @c:0 + IDENT [7] { + name: @it:1:0 } - CONSTANT [12] { value: 1 } + CONSTANT [8] { value: 1 } } } } } } } - LIST [13] { + LIST [9] { elements: { - COMPREHENSION [14] { - iter_var: @c:0 + COMPREHENSION [10] { + iter_var: @it:1:0 iter_range: { - IDENT [15] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [16] { + LIST [11] { elements: { + CONSTANT [12] { value: 1 } + CONSTANT [13] { value: 2 } + CONSTANT [14] { value: 3 } } } } - loop_condition: { - CONSTANT [17] { value: true } - } - loop_step: { - IDENT [18] { - name: @index1 - } - } - result: { - IDENT [19] { - name: @x:0 - } - } - } - } - } - CALL [20] { - function: _+_ - args: { - IDENT [21] { - name: @x:2 - } - LIST [22] { - elements: { - CALL [23] { - function: _+_ - args: { - IDENT [24] { - name: @c:2 - } - CONSTANT [25] { value: 1 } - } - } - } - } - } - } - LIST [26] { - elements: { - COMPREHENSION [27] { - iter_var: @c:2 - iter_range: { - IDENT [28] { - name: @index0 - } - } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [29] { + LIST [15] { elements: { } } } loop_condition: { - CONSTANT [30] { value: true } + CONSTANT [16] { value: true } } loop_step: { - IDENT [31] { - name: @index3 + IDENT [17] { + name: @index0 } } result: { - IDENT [32] { - name: @x:2 + IDENT [18] { + name: @ac:1:0 } } } } } - } - } - CALL [33] { - function: _==_ - args: { - COMPREHENSION [34] { - iter_var: @c:1 + COMPREHENSION [19] { + iter_var: @it:0:0 iter_range: { - IDENT [35] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [36] { + LIST [20] { elements: { + CONSTANT [21] { value: 1 } + CONSTANT [22] { value: 2 } + CONSTANT [23] { value: 3 } } } } - loop_condition: { - CONSTANT [37] { value: true } - } - loop_step: { - CALL [38] { - function: _+_ - args: { - IDENT [39] { - name: @x:1 - } - IDENT [40] { - name: @index2 - } - } - } - } - result: { - IDENT [41] { - name: @x:1 - } - } - } - COMPREHENSION [42] { - iter_var: @c:3 - iter_range: { - IDENT [43] { - name: @index0 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [44] { + LIST [24] { elements: { } } } loop_condition: { - CONSTANT [45] { value: true } + CONSTANT [25] { value: true } } loop_step: { - CALL [46] { + CALL [26] { function: _+_ args: { - IDENT [47] { - name: @x:3 + IDENT [27] { + name: @ac:0:0 } - IDENT [48] { - name: @index4 + IDENT [28] { + name: @index1 } } } } result: { - IDENT [49] { - name: @x:3 + IDENT [29] { + name: @ac:0:0 } } } } } + CALL [30] { + function: _==_ + args: { + IDENT [31] { + name: @index2 + } + IDENT [32] { + name: @index2 + } + } + } } } Test case: INCLUSION_LIST @@ -2676,7 +2295,7 @@ CALL [1] { function: _+_ args: { IDENT [14] { - name: @x:0 + name: @ac:1:0 } LIST [15] { elements: { @@ -2693,13 +2312,13 @@ CALL [1] { LIST [19] { elements: { COMPREHENSION [20] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [21] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [22] { elements: { @@ -2716,7 +2335,7 @@ CALL [1] { } result: { IDENT [25] { - name: @x:0 + name: @ac:1:0 } } } @@ -2728,13 +2347,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [27] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [28] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [29] { elements: { @@ -2749,7 +2368,7 @@ CALL [1] { function: _+_ args: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } IDENT [33] { name: @index3 @@ -2759,7 +2378,7 @@ CALL [1] { } result: { IDENT [34] { - name: @x:1 + name: @ac:0:0 } } } @@ -2826,7 +2445,7 @@ CALL [1] { function: _||_ args: { IDENT [16] { - name: @x:0 + name: @ac:0:0 } CALL [17] { function: _>_ @@ -2835,7 +2454,7 @@ CALL [1] { function: _-_ args: { IDENT [19] { - name: @c:0 + name: @it:0:0 } CONSTANT [20] { value: 1 } } @@ -2846,13 +2465,13 @@ CALL [1] { } } COMPREHENSION [22] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { IDENT [23] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [24] { value: false } } @@ -2864,7 +2483,7 @@ CALL [1] { function: !_ args: { IDENT [27] { - name: @x:0 + name: @ac:0:0 } } } @@ -2878,7 +2497,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:0 + name: @ac:0:0 } } } @@ -2909,10 +2528,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2920,10 +2539,10 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } @@ -2931,7 +2550,7 @@ CALL [1] { function: _+_ args: { IDENT [10] { - name: @x:0 + name: @ac:1:0 } LIST [11] { elements: { @@ -2953,7 +2572,7 @@ CALL [1] { function: _+_ args: { IDENT [16] { - name: @x:1 + name: @ac:0:0 } LIST [17] { elements: { @@ -2974,10 +2593,10 @@ CALL [1] { } } COMPREHENSION [21] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [22] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [23] { elements: { @@ -2986,7 +2605,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [26] { elements: { @@ -3003,12 +2622,12 @@ CALL [1] { } result: { IDENT [29] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [30] { elements: { @@ -3025,7 +2644,7 @@ CALL [1] { } result: { IDENT [33] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline index 0bfb05eaf..69d2d6af5 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline @@ -1171,36 +1171,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - LIST [7] { - elements: { - COMPREHENSION [8] { - iter_var: @c:0 + COMPREHENSION [4] { + iter_var: @it:0:0 iter_range: { - IDENT [9] { - name: @index0 + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [10] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [11] { + CALL [8] { function: @not_strictly_false args: { - CALL [12] { + CALL [9] { function: !_ args: { - IDENT [13] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1208,54 +1200,56 @@ CALL [1] { } } loop_step: { - CALL [14] { + CALL [11] { function: _||_ args: { - IDENT [15] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [16] { + CALL [13] { function: _>_ args: { - IDENT [17] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [18] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [19] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } } } - LIST [20] { + LIST [17] { elements: { - COMPREHENSION [21] { - iter_var: @c:1 + COMPREHENSION [18] { + iter_var: @it:0:0 iter_range: { - IDENT [22] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: 2 } + } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [23] { value: false } + CONSTANT [21] { value: false } } loop_condition: { - CALL [24] { + CALL [22] { function: @not_strictly_false args: { - CALL [25] { + CALL [23] { function: !_ args: { - IDENT [26] { - name: @x:1 + IDENT [24] { + name: @ac:0:0 } } } @@ -1263,198 +1257,81 @@ CALL [1] { } } loop_step: { - CALL [27] { + CALL [25] { function: _||_ args: { - IDENT [28] { - name: @x:1 + IDENT [26] { + name: @ac:0:0 } - CALL [29] { + CALL [27] { function: _>_ args: { - IDENT [30] { - name: @c:1 + IDENT [28] { + name: @it:0:0 } - CONSTANT [31] { value: 0 } + CONSTANT [29] { value: 1 } } } } } } result: { - IDENT [32] { - name: @x:1 + IDENT [30] { + name: @ac:0:0 } } } } } - LIST [33] { - elements: { - COMPREHENSION [34] { - iter_var: @c:2 - iter_range: { - IDENT [35] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [36] { value: false } - } - loop_condition: { - CALL [37] { - function: @not_strictly_false - args: { - CALL [38] { - function: !_ - args: { - IDENT [39] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [40] { - function: _||_ - args: { - IDENT [41] { - name: @x:2 - } - CALL [42] { - function: _>_ - args: { - IDENT [43] { - name: @c:2 - } - CONSTANT [44] { value: 1 } - } - } - } - } - } - result: { - IDENT [45] { - name: @x:2 - } - } + CALL [31] { + function: size + args: { + IDENT [32] { + name: @index0 } } } - LIST [46] { - elements: { - COMPREHENSION [47] { - iter_var: @c:3 - iter_range: { - IDENT [48] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [49] { value: false } - } - loop_condition: { - CALL [50] { - function: @not_strictly_false - args: { - CALL [51] { - function: !_ - args: { - IDENT [52] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [53] { - function: _||_ - args: { - IDENT [54] { - name: @x:3 - } - CALL [55] { - function: _>_ - args: { - IDENT [56] { - name: @c:3 - } - CONSTANT [57] { value: 1 } - } - } - } - } - } - result: { - IDENT [58] { - name: @x:3 - } - } + CALL [33] { + function: size + args: { + IDENT [34] { + name: @index1 } } } - CALL [59] { + } + } + CALL [35] { + function: _==_ + args: { + CALL [36] { function: _+_ args: { - CALL [60] { + CALL [37] { function: _+_ args: { - CALL [61] { + CALL [38] { function: _+_ args: { - CALL [62] { - function: size - args: { - IDENT [63] { - name: @index2 - } - } + IDENT [39] { + name: @index2 } - CALL [64] { - function: size - args: { - IDENT [65] { - name: @index3 - } - } + IDENT [40] { + name: @index2 } } } - CALL [66] { - function: size - args: { - IDENT [67] { - name: @index4 - } - } + IDENT [41] { + name: @index3 } } } - CALL [68] { - function: size - args: { - IDENT [69] { - name: @index5 - } - } + IDENT [42] { + name: @index3 } } } - } - } - CALL [70] { - function: _==_ - args: { - IDENT [71] { - name: @index6 - } - CONSTANT [72] { value: 4 } + CONSTANT [43] { value: 4 } } } } @@ -1469,91 +1346,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - LIST [7] { - elements: { - COMPREHENSION [8] { - iter_var: @c:0 + COMPREHENSION [4] { + iter_var: @it:0:0 iter_range: { - IDENT [9] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [10] { value: false } - } - loop_condition: { - CALL [11] { - function: @not_strictly_false - args: { - CALL [12] { - function: !_ - args: { - IDENT [13] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [14] { - function: _||_ - args: { - IDENT [15] { - name: @x:0 - } - CALL [16] { - function: _>_ - args: { - IDENT [17] { - name: @c:0 - } - CONSTANT [18] { value: 0 } - } - } + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } } } } - result: { - IDENT [19] { - name: @x:0 - } - } - } - } - } - LIST [20] { - elements: { - COMPREHENSION [21] { - iter_var: @c:1 - iter_range: { - IDENT [22] { - name: @index0 - } - } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [23] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [24] { + CALL [8] { function: @not_strictly_false args: { - CALL [25] { + CALL [9] { function: !_ args: { - IDENT [26] { - name: @x:1 + IDENT [10] { + name: @ac:0:0 } } } @@ -1561,109 +1375,56 @@ CALL [1] { } } loop_step: { - CALL [27] { + CALL [11] { function: _||_ args: { - IDENT [28] { - name: @x:1 + IDENT [12] { + name: @ac:0:0 } - CALL [29] { + CALL [13] { function: _>_ args: { - IDENT [30] { - name: @c:1 + IDENT [14] { + name: @it:0:0 } - CONSTANT [31] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [32] { - name: @x:1 + IDENT [16] { + name: @ac:0:0 } } } } } - LIST [33] { + LIST [17] { elements: { - COMPREHENSION [34] { - iter_var: @c:2 + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [35] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [36] { value: false } - } - loop_condition: { - CALL [37] { - function: @not_strictly_false - args: { - CALL [38] { - function: !_ - args: { - IDENT [39] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [40] { - function: _||_ - args: { - IDENT [41] { - name: @x:2 - } - CALL [42] { - function: _==_ - args: { - IDENT [43] { - name: @c:2 - } - CONSTANT [44] { value: "a" } - } - } + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } } } } - result: { - IDENT [45] { - name: @x:2 - } - } - } - } - } - LIST [46] { - elements: { - COMPREHENSION [47] { - iter_var: @c:3 - iter_range: { - IDENT [48] { - name: @index1 - } - } - accu_var: @x:3 + accu_var: @ac:0:1 accu_init: { - CONSTANT [49] { value: false } + CONSTANT [21] { value: false } } loop_condition: { - CALL [50] { + CALL [22] { function: @not_strictly_false args: { - CALL [51] { + CALL [23] { function: !_ args: { - IDENT [52] { - name: @x:3 + IDENT [24] { + name: @ac:0:1 } } } @@ -1671,27 +1432,27 @@ CALL [1] { } } loop_step: { - CALL [53] { + CALL [25] { function: _||_ args: { - IDENT [54] { - name: @x:3 + IDENT [26] { + name: @ac:0:1 } - CALL [55] { + CALL [27] { function: _==_ args: { - IDENT [56] { - name: @c:3 + IDENT [28] { + name: @it:0:1 } - CONSTANT [57] { value: "a" } + CONSTANT [29] { value: "a" } } } } } } result: { - IDENT [58] { - name: @x:3 + IDENT [30] { + name: @ac:0:1 } } } @@ -1699,42 +1460,42 @@ CALL [1] { } } } - CALL [59] { + CALL [31] { function: _==_ args: { - CALL [60] { + CALL [32] { function: _+_ args: { - CALL [61] { + CALL [33] { function: _+_ args: { - CALL [62] { + CALL [34] { function: _+_ args: { - IDENT [63] { - name: @index2 + IDENT [35] { + name: @index0 } - IDENT [64] { - name: @index3 + IDENT [36] { + name: @index0 } } } - IDENT [65] { - name: @index4 + IDENT [37] { + name: @index1 } } } - IDENT [66] { - name: @index5 + IDENT [38] { + name: @index1 } } } - LIST [67] { + LIST [39] { elements: { - CONSTANT [68] { value: true } - CONSTANT [69] { value: true } - CONSTANT [70] { value: true } - CONSTANT [71] { value: true } + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } } } } @@ -1749,141 +1510,101 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - CALL [5] { - function: _&&_ - args: { - COMPREHENSION [6] { - iter_var: @c:0 - iter_range: { - IDENT [7] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [8] { value: false } + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } } - loop_condition: { - CALL [9] { - function: @not_strictly_false + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ args: { - CALL [10] { - function: !_ - args: { - IDENT [11] { - name: @x:0 - } - } + IDENT [9] { + name: @ac:0:0 } } } } - loop_step: { + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } CALL [12] { - function: _||_ + function: _>_ args: { IDENT [13] { - name: @x:0 - } - CALL [14] { - function: _>_ - args: { - IDENT [15] { - name: @c:0 - } - CONSTANT [16] { value: 0 } - } + name: @it:0:0 } + CONSTANT [14] { value: 0 } } } } - result: { - IDENT [17] { - name: @x:0 - } - } } - COMPREHENSION [18] { - iter_var: @c:1 - iter_range: { + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { IDENT [19] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [20] { value: false } - } - loop_condition: { - CALL [21] { - function: @not_strictly_false - args: { - CALL [22] { - function: !_ - args: { - IDENT [23] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [24] { - function: _||_ - args: { - IDENT [25] { - name: @x:1 - } - CALL [26] { - function: _>_ - args: { - IDENT [27] { - name: @c:1 - } - CONSTANT [28] { value: 0 } - } - } - } - } - } - result: { - IDENT [29] { - name: @x:1 + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [30] { + CALL [21] { function: _&&_ args: { - COMPREHENSION [31] { - iter_var: @c:2 + COMPREHENSION [22] { + iter_var: @it:0:0 iter_range: { - IDENT [32] { - name: @index0 + LIST [23] { + elements: { + CONSTANT [24] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [33] { value: false } + CONSTANT [25] { value: false } } loop_condition: { - CALL [34] { + CALL [26] { function: @not_strictly_false args: { - CALL [35] { + CALL [27] { function: !_ args: { - IDENT [36] { - name: @x:2 + IDENT [28] { + name: @ac:0:0 } } } @@ -1891,52 +1612,38 @@ CALL [1] { } } loop_step: { - CALL [37] { - function: _||_ - args: { - IDENT [38] { - name: @x:2 - } - CALL [39] { - function: _>_ - args: { - IDENT [40] { - name: @c:2 - } - CONSTANT [41] { value: 1 } - } - } - } + IDENT [29] { + name: @index1 } } result: { - IDENT [42] { - name: @x:2 + IDENT [30] { + name: @ac:0:0 } } } - COMPREHENSION [43] { - iter_var: @c:3 + COMPREHENSION [31] { + iter_var: @it:0:0 iter_range: { - LIST [44] { + LIST [32] { elements: { - CONSTANT [45] { value: 2 } + CONSTANT [33] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [46] { value: false } + CONSTANT [34] { value: false } } loop_condition: { - CALL [47] { + CALL [35] { function: @not_strictly_false args: { - CALL [48] { + CALL [36] { function: !_ args: { - IDENT [49] { - name: @x:3 + IDENT [37] { + name: @ac:0:0 } } } @@ -1944,27 +1651,13 @@ CALL [1] { } } loop_step: { - CALL [50] { - function: _||_ - args: { - IDENT [51] { - name: @x:3 - } - CALL [52] { - function: _>_ - args: { - IDENT [53] { - name: @c:3 - } - CONSTANT [54] { value: 1 } - } - } - } + IDENT [38] { + name: @index1 } } result: { - IDENT [55] { - name: @x:3 + IDENT [39] { + name: @ac:0:0 } } } @@ -1972,13 +1665,21 @@ CALL [1] { } } } - CALL [56] { + CALL [40] { function: _&&_ args: { - IDENT [57] { - name: @index1 + CALL [41] { + function: _&&_ + args: { + IDENT [42] { + name: @index0 + } + IDENT [43] { + name: @index0 + } + } } - IDENT [58] { + IDENT [44] { name: @index2 } } @@ -2008,13 +1709,13 @@ CALL [1] { } } COMPREHENSION [11] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [12] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [13] { elements: { @@ -2029,7 +1730,7 @@ CALL [1] { function: _+_ args: { IDENT [16] { - name: @x:0 + name: @ac:1:0 } LIST [17] { elements: { @@ -2037,7 +1738,7 @@ CALL [1] { function: _+_ args: { IDENT [19] { - name: @c:0 + name: @it:1:0 } CONSTANT [20] { value: 1 } } @@ -2049,7 +1750,7 @@ CALL [1] { } result: { IDENT [21] { - name: @x:0 + name: @ac:1:0 } } } @@ -2059,13 +1760,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [23] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [24] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [25] { elements: { @@ -2080,7 +1781,7 @@ CALL [1] { function: _+_ args: { IDENT [28] { - name: @x:1 + name: @ac:0:0 } LIST [29] { elements: { @@ -2094,7 +1795,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2124,7 +1825,7 @@ CALL [1] { LIST [2] { elements: { COMPREHENSION [3] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [4] { elements: { @@ -2134,7 +1835,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [8] { elements: { @@ -2152,10 +1853,10 @@ CALL [1] { function: _==_ args: { IDENT [12] { - name: @c:0 + name: @it:1:0 } IDENT [13] { - name: @c:1 + name: @it:0:0 } } } @@ -2163,26 +1864,26 @@ CALL [1] { function: _+_ args: { IDENT [15] { - name: @x:0 + name: @ac:1:0 } LIST [16] { elements: { IDENT [17] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [18] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [19] { - name: @x:0 + name: @ac:1:0 } } } @@ -2192,7 +1893,7 @@ CALL [1] { function: _==_ args: { COMPREHENSION [21] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [22] { elements: { @@ -2201,7 +1902,7 @@ CALL [1] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [25] { elements: { @@ -2216,7 +1917,7 @@ CALL [1] { function: _+_ args: { IDENT [28] { - name: @x:1 + name: @ac:0:0 } LIST [29] { elements: { @@ -2230,7 +1931,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2260,46 +1961,43 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - COMPREHENSION [7] { - iter_var: @c:0 + COMPREHENSION [3] { + iter_var: @it:1:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + CONSTANT [6] { value: 2 } + CONSTANT [7] { value: 3 } + } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { - LIST [9] { + LIST [8] { elements: { } } } loop_condition: { - CONSTANT [10] { value: true } + CONSTANT [9] { value: true } } loop_step: { - CALL [11] { + CALL [10] { function: _+_ args: { - IDENT [12] { - name: @x:0 + IDENT [11] { + name: @ac:1:0 } - LIST [13] { + LIST [12] { elements: { - CALL [14] { + CALL [13] { function: _+_ args: { - IDENT [15] { - name: @c:0 + IDENT [14] { + name: @it:1:0 } - CONSTANT [16] { value: 1 } + CONSTANT [15] { value: 1 } } } } @@ -2308,45 +2006,43 @@ CALL [1] { } } result: { - IDENT [17] { - name: @x:0 + IDENT [16] { + name: @ac:1:0 } } } - COMPREHENSION [18] { - iter_var: @c:2 + COMPREHENSION [17] { + iter_var: @it:0:0 iter_range: { - IDENT [19] { - name: @index0 + LIST [18] { + elements: { + CONSTANT [19] { value: 1 } + CONSTANT [20] { value: 2 } + CONSTANT [21] { value: 3 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - LIST [20] { + LIST [22] { elements: { } } } loop_condition: { - CONSTANT [21] { value: true } + CONSTANT [23] { value: true } } loop_step: { - CALL [22] { + CALL [24] { function: _+_ args: { - IDENT [23] { - name: @x:2 + IDENT [25] { + name: @ac:0:0 } - LIST [24] { + LIST [26] { elements: { - CALL [25] { - function: _+_ - args: { - IDENT [26] { - name: @c:2 - } - CONSTANT [27] { value: 1 } - } + IDENT [27] { + name: @index0 } } } @@ -2355,7 +2051,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:2 + name: @ac:0:0 } } } @@ -2364,85 +2060,11 @@ CALL [1] { CALL [29] { function: _==_ args: { - COMPREHENSION [30] { - iter_var: @c:1 - iter_range: { - IDENT [31] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [32] { - elements: { - } - } - } - loop_condition: { - CONSTANT [33] { value: true } - } - loop_step: { - CALL [34] { - function: _+_ - args: { - IDENT [35] { - name: @x:1 - } - LIST [36] { - elements: { - IDENT [37] { - name: @index1 - } - } - } - } - } - } - result: { - IDENT [38] { - name: @x:1 - } - } + IDENT [30] { + name: @index1 } - COMPREHENSION [39] { - iter_var: @c:3 - iter_range: { - IDENT [40] { - name: @index0 - } - } - accu_var: @x:3 - accu_init: { - LIST [41] { - elements: { - } - } - } - loop_condition: { - CONSTANT [42] { value: true } - } - loop_step: { - CALL [43] { - function: _+_ - args: { - IDENT [44] { - name: @x:3 - } - LIST [45] { - elements: { - IDENT [46] { - name: @index2 - } - } - } - } - } - } - result: { - IDENT [47] { - name: @x:3 - } - } + IDENT [31] { + name: @index1 } } } @@ -2613,13 +2235,13 @@ CALL [1] { } } COMPREHENSION [13] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [14] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [15] { elements: { @@ -2634,7 +2256,7 @@ CALL [1] { function: _+_ args: { IDENT [18] { - name: @x:0 + name: @ac:1:0 } LIST [19] { elements: { @@ -2651,7 +2273,7 @@ CALL [1] { } result: { IDENT [23] { - name: @x:0 + name: @ac:1:0 } } } @@ -2661,13 +2283,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [25] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [26] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [27] { elements: { @@ -2682,7 +2304,7 @@ CALL [1] { function: _+_ args: { IDENT [30] { - name: @x:1 + name: @ac:0:0 } LIST [31] { elements: { @@ -2696,7 +2318,7 @@ CALL [1] { } result: { IDENT [33] { - name: @x:1 + name: @ac:0:0 } } } @@ -2738,7 +2360,7 @@ CALL [1] { } } COMPREHENSION [8] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [9] { elements: { @@ -2763,7 +2385,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [16] { value: false } } @@ -2775,7 +2397,7 @@ CALL [1] { function: !_ args: { IDENT [19] { - name: @x:0 + name: @ac:0:0 } } } @@ -2787,7 +2409,7 @@ CALL [1] { function: _||_ args: { IDENT [21] { - name: @x:0 + name: @ac:0:0 } CALL [22] { function: _>_ @@ -2796,7 +2418,7 @@ CALL [1] { function: _-_ args: { IDENT [24] { - name: @c:0 + name: @it:0:0 } CONSTANT [25] { value: 1 } } @@ -2809,7 +2431,7 @@ CALL [1] { } result: { IDENT [27] { - name: @x:0 + name: @ac:0:0 } } } @@ -2840,10 +2462,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2851,15 +2473,15 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [10] { elements: { @@ -2868,7 +2490,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [13] { elements: { @@ -2883,7 +2505,7 @@ CALL [1] { function: _+_ args: { IDENT [16] { - name: @x:0 + name: @ac:1:0 } LIST [17] { elements: { @@ -2904,20 +2526,20 @@ CALL [1] { } result: { IDENT [21] { - name: @x:0 + name: @ac:1:0 } } } } } COMPREHENSION [22] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [23] { name: @index2 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [24] { elements: { @@ -2932,7 +2554,7 @@ CALL [1] { function: _+_ args: { IDENT [27] { - name: @x:1 + name: @ac:0:0 } LIST [28] { elements: { @@ -2953,7 +2575,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline index ed7daab1e..e27f91a0d 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline @@ -1151,101 +1151,33 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - CALL [7] { + CALL [3] { function: size args: { - LIST [8] { + LIST [4] { elements: { - COMPREHENSION [9] { - iter_var: @c:0 + COMPREHENSION [5] { + iter_var: @it:0:0 iter_range: { - IDENT [10] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [11] { value: false } - } - loop_condition: { - CALL [12] { - function: @not_strictly_false - args: { - CALL [13] { - function: !_ - args: { - IDENT [14] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [15] { - function: _||_ - args: { - IDENT [16] { - name: @x:0 - } - CALL [17] { - function: _>_ - args: { - IDENT [18] { - name: @c:0 - } - CONSTANT [19] { value: 0 } - } - } + LIST [6] { + elements: { + CONSTANT [7] { value: 1 } } } } - result: { - IDENT [20] { - name: @x:0 - } - } - } - } - } - } - } - CALL [21] { - function: size - args: { - LIST [22] { - elements: { - COMPREHENSION [23] { - iter_var: @c:1 - iter_range: { - IDENT [24] { - name: @index0 - } - } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { - CONSTANT [25] { value: false } + CONSTANT [8] { value: false } } loop_condition: { - CALL [26] { + CALL [9] { function: @not_strictly_false args: { - CALL [27] { + CALL [10] { function: !_ args: { - IDENT [28] { - name: @x:1 + IDENT [11] { + name: @ac:0:0 } } } @@ -1253,27 +1185,27 @@ CALL [1] { } } loop_step: { - CALL [29] { + CALL [12] { function: _||_ args: { - IDENT [30] { - name: @x:1 + IDENT [13] { + name: @ac:0:0 } - CALL [31] { + CALL [14] { function: _>_ args: { - IDENT [32] { - name: @c:1 + IDENT [15] { + name: @it:0:0 } - CONSTANT [33] { value: 0 } + CONSTANT [16] { value: 0 } } } } } } result: { - IDENT [34] { - name: @x:1 + IDENT [17] { + name: @ac:0:0 } } } @@ -1281,91 +1213,33 @@ CALL [1] { } } } - CALL [35] { + CALL [18] { function: size args: { - LIST [36] { + LIST [19] { elements: { - COMPREHENSION [37] { - iter_var: @c:2 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [38] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [39] { value: false } - } - loop_condition: { - CALL [40] { - function: @not_strictly_false - args: { - CALL [41] { - function: !_ - args: { - IDENT [42] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [43] { - function: _||_ - args: { - IDENT [44] { - name: @x:2 - } - CALL [45] { - function: _>_ - args: { - IDENT [46] { - name: @c:2 - } - CONSTANT [47] { value: 1 } - } - } + LIST [21] { + elements: { + CONSTANT [22] { value: 2 } } } } - result: { - IDENT [48] { - name: @x:2 - } - } - } - } - } - } - } - CALL [49] { - function: size - args: { - LIST [50] { - elements: { - COMPREHENSION [51] { - iter_var: @c:3 - iter_range: { - IDENT [52] { - name: @index1 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [53] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [54] { + CALL [24] { function: @not_strictly_false args: { - CALL [55] { + CALL [25] { function: !_ args: { - IDENT [56] { - name: @x:3 + IDENT [26] { + name: @ac:0:0 } } } @@ -1373,27 +1247,27 @@ CALL [1] { } } loop_step: { - CALL [57] { + CALL [27] { function: _||_ args: { - IDENT [58] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } - CALL [59] { + CALL [29] { function: _>_ args: { - IDENT [60] { - name: @c:3 + IDENT [30] { + name: @it:0:0 } - CONSTANT [61] { value: 1 } + CONSTANT [31] { value: 1 } } } } } } result: { - IDENT [62] { - name: @x:3 + IDENT [32] { + name: @ac:0:0 } } } @@ -1403,322 +1277,43 @@ CALL [1] { } } } - CALL [63] { + CALL [33] { function: _==_ args: { - CALL [64] { + CALL [34] { function: _+_ args: { - CALL [65] { + CALL [35] { function: _+_ args: { - CALL [66] { + CALL [36] { function: _+_ args: { - IDENT [67] { - name: @index2 - } - IDENT [68] { - name: @index3 - } - } - } - IDENT [69] { - name: @index4 - } - } - } - IDENT [70] { - name: @index5 - } - } - } - CONSTANT [71] { value: 4 } - } - } - } -} -Test case: MULTIPLE_MACROS_2 -Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] -=====> -CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - CALL [7] { - function: _+_ - args: { - LIST [8] { - elements: { - COMPREHENSION [9] { - iter_var: @c:0 - iter_range: { - IDENT [10] { + IDENT [37] { name: @index0 } - } - accu_var: @x:0 - accu_init: { - CONSTANT [11] { value: false } - } - loop_condition: { - CALL [12] { - function: @not_strictly_false - args: { - CALL [13] { - function: !_ - args: { - IDENT [14] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [15] { - function: _||_ - args: { - IDENT [16] { - name: @x:0 - } - CALL [17] { - function: _>_ - args: { - IDENT [18] { - name: @c:0 - } - CONSTANT [19] { value: 0 } - } - } - } - } - } - result: { - IDENT [20] { - name: @x:0 - } - } - } - } - } - LIST [21] { - elements: { - COMPREHENSION [22] { - iter_var: @c:1 - iter_range: { - IDENT [23] { + IDENT [38] { name: @index0 } } - accu_var: @x:1 - accu_init: { - CONSTANT [24] { value: false } - } - loop_condition: { - CALL [25] { - function: @not_strictly_false - args: { - CALL [26] { - function: !_ - args: { - IDENT [27] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [28] { - function: _||_ - args: { - IDENT [29] { - name: @x:1 - } - CALL [30] { - function: _>_ - args: { - IDENT [31] { - name: @c:1 - } - CONSTANT [32] { value: 0 } - } - } - } - } - } - result: { - IDENT [33] { - name: @x:1 - } - } } - } - } - } - } - CALL [34] { - function: _+_ - args: { - IDENT [35] { - name: @index2 - } - LIST [36] { - elements: { - COMPREHENSION [37] { - iter_var: @c:2 - iter_range: { - IDENT [38] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [39] { value: false } - } - loop_condition: { - CALL [40] { - function: @not_strictly_false - args: { - CALL [41] { - function: !_ - args: { - IDENT [42] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [43] { - function: _||_ - args: { - IDENT [44] { - name: @x:2 - } - CALL [45] { - function: _==_ - args: { - IDENT [46] { - name: @c:2 - } - CONSTANT [47] { value: "a" } - } - } - } - } - } - result: { - IDENT [48] { - name: @x:2 - } - } + IDENT [39] { + name: @index1 } } } - } - } - CALL [49] { - function: _+_ - args: { - IDENT [50] { - name: @index3 - } - LIST [51] { - elements: { - COMPREHENSION [52] { - iter_var: @c:3 - iter_range: { - IDENT [53] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [54] { value: false } - } - loop_condition: { - CALL [55] { - function: @not_strictly_false - args: { - CALL [56] { - function: !_ - args: { - IDENT [57] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [58] { - function: _||_ - args: { - IDENT [59] { - name: @x:3 - } - CALL [60] { - function: _==_ - args: { - IDENT [61] { - name: @c:3 - } - CONSTANT [62] { value: "a" } - } - } - } - } - } - result: { - IDENT [63] { - name: @x:3 - } - } - } - } + IDENT [40] { + name: @index1 } } } - } - } - CALL [64] { - function: _==_ - args: { - IDENT [65] { - name: @index4 - } - LIST [66] { - elements: { - CONSTANT [67] { value: true } - CONSTANT [68] { value: true } - CONSTANT [69] { value: true } - CONSTANT [70] { value: true } - } - } + CONSTANT [41] { value: 4 } } } } } -Test case: MULTIPLE_MACROS_3 -Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> CALL [1] { function: cel.@block @@ -1727,37 +1322,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - } - } - CALL [5] { - function: _&&_ - args: { - CALL [6] { - function: _&&_ - args: { - COMPREHENSION [7] { - iter_var: @c:0 + COMPREHENSION [4] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [10] { + CALL [8] { function: @not_strictly_false args: { - CALL [11] { + CALL [9] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1765,38 +1351,44 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [11] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [15] { + CALL [13] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + } + } + LIST [17] { + elements: { + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { CONSTANT [21] { value: false } } @@ -1808,7 +1400,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:1 } } } @@ -1820,15 +1412,15 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:1 } CALL [27] { - function: _>_ + function: _==_ args: { IDENT [28] { - name: @c:1 + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [29] { value: "a" } } } } @@ -1836,35 +1428,175 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:1 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + CALL [32] { + function: _+_ + args: { + CALL [33] { + function: _+_ + args: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @index0 + } + IDENT [36] { + name: @index0 + } + } + } + IDENT [37] { + name: @index1 + } + } + } + IDENT [38] { + name: @index1 + } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [31] { + } + } + CALL [21] { + function: _&&_ + args: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @index0 + } + IDENT [24] { + name: @index0 + } + } + } + CALL [25] { function: _&&_ args: { - COMPREHENSION [32] { - iter_var: @c:2 + COMPREHENSION [26] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 + LIST [27] { + elements: { + CONSTANT [28] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [34] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [35] { + CALL [30] { function: @not_strictly_false args: { - CALL [36] { + CALL [31] { function: !_ args: { - IDENT [37] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1872,52 +1604,38 @@ CALL [1] { } } loop_step: { - CALL [38] { - function: _||_ - args: { - IDENT [39] { - name: @x:2 - } - CALL [40] { - function: _>_ - args: { - IDENT [41] { - name: @c:2 - } - CONSTANT [42] { value: 1 } - } - } - } + IDENT [33] { + name: @index1 } } result: { - IDENT [43] { - name: @x:2 + IDENT [34] { + name: @ac:0:0 } } } - COMPREHENSION [44] { - iter_var: @c:3 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - LIST [45] { + LIST [36] { elements: { - CONSTANT [46] { value: 2 } + CONSTANT [37] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [47] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [48] { + CALL [39] { function: @not_strictly_false args: { - CALL [49] { + CALL [40] { function: !_ args: { - IDENT [50] { - name: @x:3 + IDENT [41] { + name: @ac:0:0 } } } @@ -1925,27 +1643,13 @@ CALL [1] { } } loop_step: { - CALL [51] { - function: _||_ - args: { - IDENT [52] { - name: @x:3 - } - CALL [53] { - function: _>_ - args: { - IDENT [54] { - name: @c:3 - } - CONSTANT [55] { value: 1 } - } - } - } + IDENT [42] { + name: @index1 } } result: { - IDENT [56] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -1980,13 +1684,13 @@ CALL [1] { LIST [11] { elements: { COMPREHENSION [12] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [13] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2001,7 +1705,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2009,7 +1713,7 @@ CALL [1] { function: _+_ args: { IDENT [20] { - name: @c:0 + name: @it:1:0 } CONSTANT [21] { value: 1 } } @@ -2021,7 +1725,7 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -2033,13 +1737,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [24] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [25] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [26] { elements: { @@ -2054,7 +1758,7 @@ CALL [1] { function: _+_ args: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } IDENT [30] { name: @index2 @@ -2064,7 +1768,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2096,7 +1800,7 @@ CALL [1] { LIST [3] { elements: { COMPREHENSION [4] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [5] { elements: { @@ -2106,7 +1810,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [9] { elements: { @@ -2124,10 +1828,10 @@ CALL [1] { function: _==_ args: { IDENT [13] { - name: @c:0 + name: @it:1:0 } IDENT [14] { - name: @c:1 + name: @it:0:0 } } } @@ -2135,26 +1839,26 @@ CALL [1] { function: _+_ args: { IDENT [16] { - name: @x:0 + name: @ac:1:0 } LIST [17] { elements: { IDENT [18] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [19] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [20] { - name: @x:0 + name: @ac:1:0 } } } @@ -2166,7 +1870,7 @@ CALL [1] { function: _==_ args: { COMPREHENSION [22] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [23] { elements: { @@ -2175,7 +1879,7 @@ CALL [1] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [26] { elements: { @@ -2190,7 +1894,7 @@ CALL [1] { function: _+_ args: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } IDENT [30] { name: @index0 @@ -2200,7 +1904,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2232,96 +1936,43 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - LIST [7] { - elements: { - COMPREHENSION [8] { - iter_var: @c:0 + COMPREHENSION [4] { + iter_var: @it:1:0 iter_range: { - IDENT [9] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [10] { + LIST [5] { elements: { + CONSTANT [6] { value: 1 } + CONSTANT [7] { value: 2 } + CONSTANT [8] { value: 3 } } } } - loop_condition: { - CONSTANT [11] { value: true } - } - loop_step: { - CALL [12] { - function: _+_ - args: { - IDENT [13] { - name: @x:0 - } - LIST [14] { - elements: { - CALL [15] { - function: _+_ - args: { - IDENT [16] { - name: @c:0 - } - CONSTANT [17] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [18] { - name: @x:0 - } - } - } - } - } - LIST [19] { - elements: { - COMPREHENSION [20] { - iter_var: @c:2 - iter_range: { - IDENT [21] { - name: @index0 - } - } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [22] { + LIST [9] { elements: { } } } loop_condition: { - CONSTANT [23] { value: true } + CONSTANT [10] { value: true } } loop_step: { - CALL [24] { + CALL [11] { function: _+_ args: { - IDENT [25] { - name: @x:2 + IDENT [12] { + name: @ac:1:0 } - LIST [26] { + LIST [13] { elements: { - CALL [27] { + CALL [14] { function: _+_ args: { - IDENT [28] { - name: @c:2 + IDENT [15] { + name: @it:1:0 } - CONSTANT [29] { value: 1 } + CONSTANT [16] { value: 1 } } } } @@ -2330,92 +1981,66 @@ CALL [1] { } } result: { - IDENT [30] { - name: @x:2 + IDENT [17] { + name: @ac:1:0 } } } } } - } - } - CALL [31] { - function: _==_ - args: { - COMPREHENSION [32] { - iter_var: @c:1 + COMPREHENSION [18] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [34] { + LIST [19] { elements: { + CONSTANT [20] { value: 1 } + CONSTANT [21] { value: 2 } + CONSTANT [22] { value: 3 } } } } - loop_condition: { - CONSTANT [35] { value: true } - } - loop_step: { - CALL [36] { - function: _+_ - args: { - IDENT [37] { - name: @x:1 - } - IDENT [38] { - name: @index1 - } - } - } - } - result: { - IDENT [39] { - name: @x:1 - } - } - } - COMPREHENSION [40] { - iter_var: @c:3 - iter_range: { - IDENT [41] { - name: @index0 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [42] { + LIST [23] { elements: { } } } loop_condition: { - CONSTANT [43] { value: true } + CONSTANT [24] { value: true } } loop_step: { - CALL [44] { + CALL [25] { function: _+_ args: { - IDENT [45] { - name: @x:3 + IDENT [26] { + name: @ac:0:0 } - IDENT [46] { - name: @index2 + IDENT [27] { + name: @index0 } } } } result: { - IDENT [47] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } } } } } + CALL [29] { + function: _==_ + args: { + IDENT [30] { + name: @index1 + } + IDENT [31] { + name: @index1 + } + } + } } } Test case: INCLUSION_LIST @@ -2585,13 +2210,13 @@ CALL [1] { LIST [13] { elements: { COMPREHENSION [14] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [15] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [16] { elements: { @@ -2606,7 +2231,7 @@ CALL [1] { function: _+_ args: { IDENT [19] { - name: @x:0 + name: @ac:1:0 } LIST [20] { elements: { @@ -2623,7 +2248,7 @@ CALL [1] { } result: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } } } @@ -2635,13 +2260,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [26] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [27] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [28] { elements: { @@ -2656,7 +2281,7 @@ CALL [1] { function: _+_ args: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } IDENT [32] { name: @index2 @@ -2666,7 +2291,7 @@ CALL [1] { } result: { IDENT [33] { - name: @x:1 + name: @ac:0:0 } } } @@ -2713,7 +2338,7 @@ CALL [1] { function: _||_ args: { COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [10] { elements: { @@ -2738,7 +2363,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [17] { value: false } } @@ -2750,7 +2375,7 @@ CALL [1] { function: !_ args: { IDENT [20] { - name: @x:0 + name: @ac:0:0 } } } @@ -2762,7 +2387,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } CALL [23] { function: _>_ @@ -2771,7 +2396,7 @@ CALL [1] { function: _-_ args: { IDENT [25] { - name: @c:0 + name: @it:0:0 } CONSTANT [26] { value: 1 } } @@ -2784,7 +2409,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:0:0 } } } @@ -2807,10 +2432,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2818,20 +2443,20 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } } } COMPREHENSION [9] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [11] { elements: { @@ -2840,7 +2465,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2855,7 +2480,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2876,12 +2501,12 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -2896,7 +2521,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2917,7 +2542,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline index 0172a0726..89e38dc92 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline @@ -1145,270 +1145,61 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - CALL [7] { - function: _+_ + CALL [3] { + function: size args: { - CALL [8] { - function: size - args: { - LIST [9] { - elements: { - COMPREHENSION [10] { - iter_var: @c:0 - iter_range: { - IDENT [11] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [12] { value: false } - } - loop_condition: { - CALL [13] { - function: @not_strictly_false - args: { - CALL [14] { - function: !_ - args: { - IDENT [15] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [16] { - function: _||_ - args: { - IDENT [17] { - name: @x:0 - } - CALL [18] { - function: _>_ - args: { - IDENT [19] { - name: @c:0 - } - CONSTANT [20] { value: 0 } - } - } - } - } - } - result: { - IDENT [21] { - name: @x:0 - } + LIST [4] { + elements: { + COMPREHENSION [5] { + iter_var: @it:0:0 + iter_range: { + LIST [6] { + elements: { + CONSTANT [7] { value: 1 } } } } - } - } - } - CALL [22] { - function: size - args: { - LIST [23] { - elements: { - COMPREHENSION [24] { - iter_var: @c:1 - iter_range: { - IDENT [25] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [26] { value: false } - } - loop_condition: { - CALL [27] { - function: @not_strictly_false - args: { - CALL [28] { - function: !_ - args: { - IDENT [29] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [30] { - function: _||_ + accu_var: @ac:0:0 + accu_init: { + CONSTANT [8] { value: false } + } + loop_condition: { + CALL [9] { + function: @not_strictly_false + args: { + CALL [10] { + function: !_ args: { - IDENT [31] { - name: @x:1 - } - CALL [32] { - function: _>_ - args: { - IDENT [33] { - name: @c:1 - } - CONSTANT [34] { value: 0 } - } + IDENT [11] { + name: @ac:0:0 } } } } - result: { - IDENT [35] { - name: @x:1 - } - } } } - } - } - } - } - } - CALL [36] { - function: _+_ - args: { - IDENT [37] { - name: @index2 - } - CALL [38] { - function: size - args: { - LIST [39] { - elements: { - COMPREHENSION [40] { - iter_var: @c:2 - iter_range: { - IDENT [41] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [42] { value: false } - } - loop_condition: { - CALL [43] { - function: @not_strictly_false - args: { - CALL [44] { - function: !_ - args: { - IDENT [45] { - name: @x:2 - } - } - } - } + loop_step: { + CALL [12] { + function: _||_ + args: { + IDENT [13] { + name: @ac:0:0 } - } - loop_step: { - CALL [46] { - function: _||_ + CALL [14] { + function: _>_ args: { - IDENT [47] { - name: @x:2 - } - CALL [48] { - function: _>_ - args: { - IDENT [49] { - name: @c:2 - } - CONSTANT [50] { value: 1 } - } + IDENT [15] { + name: @it:0:0 } + CONSTANT [16] { value: 0 } } } } - result: { - IDENT [51] { - name: @x:2 - } - } } } - } - } - } - } - } - CALL [52] { - function: _+_ - args: { - IDENT [53] { - name: @index3 - } - CALL [54] { - function: size - args: { - LIST [55] { - elements: { - COMPREHENSION [56] { - iter_var: @c:3 - iter_range: { - IDENT [57] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [58] { value: false } - } - loop_condition: { - CALL [59] { - function: @not_strictly_false - args: { - CALL [60] { - function: !_ - args: { - IDENT [61] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [62] { - function: _||_ - args: { - IDENT [63] { - name: @x:3 - } - CALL [64] { - function: _>_ - args: { - IDENT [65] { - name: @c:3 - } - CONSTANT [66] { value: 1 } - } - } - } - } - } - result: { - IDENT [67] { - name: @x:3 - } - } + result: { + IDENT [17] { + name: @ac:0:0 } } } @@ -1416,177 +1207,33 @@ CALL [1] { } } } - } - } - CALL [68] { - function: _==_ - args: { - IDENT [69] { - name: @index4 - } - CONSTANT [70] { value: 4 } - } - } - } -} -Test case: MULTIPLE_MACROS_2 -Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] -=====> -CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - CALL [7] { - function: _+_ + CALL [18] { + function: size args: { - CALL [8] { - function: _+_ - args: { - LIST [9] { - elements: { - COMPREHENSION [10] { - iter_var: @c:0 - iter_range: { - IDENT [11] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [12] { value: false } - } - loop_condition: { - CALL [13] { - function: @not_strictly_false - args: { - CALL [14] { - function: !_ - args: { - IDENT [15] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [16] { - function: _||_ - args: { - IDENT [17] { - name: @x:0 - } - CALL [18] { - function: _>_ - args: { - IDENT [19] { - name: @c:0 - } - CONSTANT [20] { value: 0 } - } - } - } - } - } - result: { - IDENT [21] { - name: @x:0 - } - } - } - } - } - LIST [22] { - elements: { - COMPREHENSION [23] { - iter_var: @c:1 - iter_range: { - IDENT [24] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [25] { value: false } - } - loop_condition: { - CALL [26] { - function: @not_strictly_false - args: { - CALL [27] { - function: !_ - args: { - IDENT [28] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [29] { - function: _||_ - args: { - IDENT [30] { - name: @x:1 - } - CALL [31] { - function: _>_ - args: { - IDENT [32] { - name: @c:1 - } - CONSTANT [33] { value: 0 } - } - } - } - } - } - result: { - IDENT [34] { - name: @x:1 - } - } - } - } - } - } - } - LIST [35] { + LIST [19] { elements: { - COMPREHENSION [36] { - iter_var: @c:2 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [37] { - name: @index1 + LIST [21] { + elements: { + CONSTANT [22] { value: 2 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [38] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [39] { + CALL [24] { function: @not_strictly_false args: { - CALL [40] { + CALL [25] { function: !_ args: { - IDENT [41] { - name: @x:2 + IDENT [26] { + name: @ac:0:0 } } } @@ -1594,27 +1241,27 @@ CALL [1] { } } loop_step: { - CALL [42] { + CALL [27] { function: _||_ args: { - IDENT [43] { - name: @x:2 + IDENT [28] { + name: @ac:0:0 } - CALL [44] { - function: _==_ + CALL [29] { + function: _>_ args: { - IDENT [45] { - name: @c:2 + IDENT [30] { + name: @it:0:0 } - CONSTANT [46] { value: "a" } + CONSTANT [31] { value: 1 } } } } } } result: { - IDENT [47] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1624,86 +1271,43 @@ CALL [1] { } } } - CALL [48] { + CALL [33] { function: _==_ args: { - CALL [49] { + CALL [34] { function: _+_ args: { - IDENT [50] { - name: @index2 - } - LIST [51] { - elements: { - COMPREHENSION [52] { - iter_var: @c:3 - iter_range: { - IDENT [53] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [54] { value: false } - } - loop_condition: { - CALL [55] { - function: @not_strictly_false - args: { - CALL [56] { - function: !_ - args: { - IDENT [57] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [58] { - function: _||_ - args: { - IDENT [59] { - name: @x:3 - } - CALL [60] { - function: _==_ - args: { - IDENT [61] { - name: @c:3 - } - CONSTANT [62] { value: "a" } - } - } - } + CALL [35] { + function: _+_ + args: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @index0 } - } - result: { - IDENT [63] { - name: @x:3 + IDENT [38] { + name: @index0 } } } + IDENT [39] { + name: @index1 + } } } + IDENT [40] { + name: @index1 + } } } - LIST [64] { - elements: { - CONSTANT [65] { value: true } - CONSTANT [66] { value: true } - CONSTANT [67] { value: true } - CONSTANT [68] { value: true } - } - } + CONSTANT [41] { value: 4 } } } } } -Test case: MULTIPLE_MACROS_3 -Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> CALL [1] { function: cel.@block @@ -1712,37 +1316,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - } - } - CALL [5] { - function: _&&_ - args: { - CALL [6] { - function: _&&_ - args: { - COMPREHENSION [7] { - iter_var: @c:0 + COMPREHENSION [4] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [10] { + CALL [8] { function: @not_strictly_false args: { - CALL [11] { + CALL [9] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1750,38 +1345,44 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [11] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [15] { + CALL [13] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + } + } + LIST [17] { + elements: { + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { CONSTANT [21] { value: false } } @@ -1793,7 +1394,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:1 } } } @@ -1805,15 +1406,15 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:1 } CALL [27] { - function: _>_ + function: _==_ args: { IDENT [28] { - name: @c:1 + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [29] { value: "a" } } } } @@ -1821,35 +1422,175 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:1 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + CALL [32] { + function: _+_ + args: { + CALL [33] { + function: _+_ + args: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @index0 + } + IDENT [36] { + name: @index0 + } + } + } + IDENT [37] { + name: @index1 + } + } + } + IDENT [38] { + name: @index1 + } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [31] { + } + } + CALL [21] { + function: _&&_ + args: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @index0 + } + IDENT [24] { + name: @index0 + } + } + } + CALL [25] { function: _&&_ args: { - COMPREHENSION [32] { - iter_var: @c:2 + COMPREHENSION [26] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 + LIST [27] { + elements: { + CONSTANT [28] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [34] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [35] { + CALL [30] { function: @not_strictly_false args: { - CALL [36] { + CALL [31] { function: !_ args: { - IDENT [37] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1857,52 +1598,38 @@ CALL [1] { } } loop_step: { - CALL [38] { - function: _||_ - args: { - IDENT [39] { - name: @x:2 - } - CALL [40] { - function: _>_ - args: { - IDENT [41] { - name: @c:2 - } - CONSTANT [42] { value: 1 } - } - } - } + IDENT [33] { + name: @index1 } } result: { - IDENT [43] { - name: @x:2 + IDENT [34] { + name: @ac:0:0 } } } - COMPREHENSION [44] { - iter_var: @c:3 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - LIST [45] { + LIST [36] { elements: { - CONSTANT [46] { value: 2 } + CONSTANT [37] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [47] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [48] { + CALL [39] { function: @not_strictly_false args: { - CALL [49] { + CALL [40] { function: !_ args: { - IDENT [50] { - name: @x:3 + IDENT [41] { + name: @ac:0:0 } } } @@ -1910,27 +1637,13 @@ CALL [1] { } } loop_step: { - CALL [51] { - function: _||_ - args: { - IDENT [52] { - name: @x:3 - } - CALL [53] { - function: _>_ - args: { - IDENT [54] { - name: @c:3 - } - CONSTANT [55] { value: 1 } - } - } - } + IDENT [42] { + name: @index1 } } result: { - IDENT [56] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -1966,18 +1679,18 @@ CALL [1] { function: _+_ args: { IDENT [12] { - name: @x:1 + name: @ac:0:0 } LIST [13] { elements: { COMPREHENSION [14] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [15] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [16] { elements: { @@ -1992,7 +1705,7 @@ CALL [1] { function: _+_ args: { IDENT [19] { - name: @x:0 + name: @ac:1:0 } LIST [20] { elements: { @@ -2000,7 +1713,7 @@ CALL [1] { function: _+_ args: { IDENT [22] { - name: @c:0 + name: @it:1:0 } CONSTANT [23] { value: 1 } } @@ -2012,7 +1725,7 @@ CALL [1] { } result: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } } } @@ -2026,13 +1739,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [26] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [27] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [28] { elements: { @@ -2049,7 +1762,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2082,12 +1795,12 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @x:1 + name: @ac:0:0 } LIST [5] { elements: { COMPREHENSION [6] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [7] { elements: { @@ -2097,7 +1810,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [11] { elements: { @@ -2115,10 +1828,10 @@ CALL [1] { function: _==_ args: { IDENT [15] { - name: @c:0 + name: @it:1:0 } IDENT [16] { - name: @c:1 + name: @it:0:0 } } } @@ -2126,26 +1839,26 @@ CALL [1] { function: _+_ args: { IDENT [18] { - name: @x:0 + name: @ac:1:0 } LIST [19] { elements: { IDENT [20] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [21] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -2159,7 +1872,7 @@ CALL [1] { function: _==_ args: { COMPREHENSION [24] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [25] { elements: { @@ -2168,7 +1881,7 @@ CALL [1] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [28] { elements: { @@ -2185,7 +1898,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2215,112 +1928,51 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - CALL [7] { + CALL [3] { function: _+_ args: { - IDENT [8] { - name: @x:1 + IDENT [4] { + name: @ac:0:0 } - LIST [9] { + LIST [5] { elements: { - COMPREHENSION [10] { - iter_var: @c:0 + COMPREHENSION [6] { + iter_var: @it:1:0 iter_range: { - IDENT [11] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [12] { + LIST [7] { elements: { + CONSTANT [8] { value: 1 } + CONSTANT [9] { value: 2 } + CONSTANT [10] { value: 3 } } } } - loop_condition: { - CONSTANT [13] { value: true } - } - loop_step: { - CALL [14] { - function: _+_ - args: { - IDENT [15] { - name: @x:0 - } - LIST [16] { - elements: { - CALL [17] { - function: _+_ - args: { - IDENT [18] { - name: @c:0 - } - CONSTANT [19] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [20] { - name: @x:0 - } - } - } - } - } - } - } - CALL [21] { - function: _+_ - args: { - IDENT [22] { - name: @x:3 - } - LIST [23] { - elements: { - COMPREHENSION [24] { - iter_var: @c:2 - iter_range: { - IDENT [25] { - name: @index0 - } - } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [26] { + LIST [11] { elements: { } } } loop_condition: { - CONSTANT [27] { value: true } + CONSTANT [12] { value: true } } loop_step: { - CALL [28] { + CALL [13] { function: _+_ args: { - IDENT [29] { - name: @x:2 + IDENT [14] { + name: @ac:1:0 } - LIST [30] { + LIST [15] { elements: { - CALL [31] { + CALL [16] { function: _+_ args: { - IDENT [32] { - name: @c:2 + IDENT [17] { + name: @it:1:0 } - CONSTANT [33] { value: 1 } + CONSTANT [18] { value: 1 } } } } @@ -2329,8 +1981,8 @@ CALL [1] { } } result: { - IDENT [34] { - name: @x:2 + IDENT [19] { + name: @ac:1:0 } } } @@ -2338,69 +1990,51 @@ CALL [1] { } } } - } - } - CALL [35] { - function: _==_ - args: { - COMPREHENSION [36] { - iter_var: @c:1 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [37] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [38] { + LIST [21] { elements: { + CONSTANT [22] { value: 1 } + CONSTANT [23] { value: 2 } + CONSTANT [24] { value: 3 } } } } - loop_condition: { - CONSTANT [39] { value: true } - } - loop_step: { - IDENT [40] { - name: @index1 - } - } - result: { - IDENT [41] { - name: @x:1 - } - } - } - COMPREHENSION [42] { - iter_var: @c:3 - iter_range: { - IDENT [43] { - name: @index0 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [44] { + LIST [25] { elements: { } } } loop_condition: { - CONSTANT [45] { value: true } + CONSTANT [26] { value: true } } loop_step: { - IDENT [46] { - name: @index2 + IDENT [27] { + name: @index0 } } result: { - IDENT [47] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } } } } } + CALL [29] { + function: _==_ + args: { + IDENT [30] { + name: @index1 + } + IDENT [31] { + name: @index1 + } + } + } } } Test case: INCLUSION_LIST @@ -2571,18 +2205,18 @@ CALL [1] { function: _+_ args: { IDENT [14] { - name: @x:1 + name: @ac:0:0 } LIST [15] { elements: { COMPREHENSION [16] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [17] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [18] { elements: { @@ -2597,7 +2231,7 @@ CALL [1] { function: _+_ args: { IDENT [21] { - name: @x:0 + name: @ac:1:0 } LIST [22] { elements: { @@ -2614,7 +2248,7 @@ CALL [1] { } result: { IDENT [26] { - name: @x:0 + name: @ac:1:0 } } } @@ -2628,13 +2262,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [28] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [29] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [30] { elements: { @@ -2651,7 +2285,7 @@ CALL [1] { } result: { IDENT [33] { - name: @x:1 + name: @ac:0:0 } } } @@ -2698,7 +2332,7 @@ CALL [1] { function: _||_ args: { COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [10] { elements: { @@ -2723,7 +2357,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [17] { value: false } } @@ -2735,7 +2369,7 @@ CALL [1] { function: !_ args: { IDENT [20] { - name: @x:0 + name: @ac:0:0 } } } @@ -2747,7 +2381,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } CALL [23] { function: _>_ @@ -2756,7 +2390,7 @@ CALL [1] { function: _-_ args: { IDENT [25] { - name: @c:0 + name: @it:0:0 } CONSTANT [26] { value: 1 } } @@ -2769,7 +2403,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:0:0 } } } @@ -2792,10 +2426,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2803,20 +2437,20 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } } } COMPREHENSION [9] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [11] { elements: { @@ -2825,7 +2459,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2840,7 +2474,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2861,12 +2495,12 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -2881,7 +2515,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2902,7 +2536,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline index 5fa185080..e40934fc9 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline @@ -1142,272 +1142,61 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - CALL [7] { - function: _+_ + CALL [3] { + function: size args: { - CALL [8] { - function: _+_ - args: { - CALL [9] { - function: size - args: { - LIST [10] { + LIST [4] { + elements: { + COMPREHENSION [5] { + iter_var: @it:0:0 + iter_range: { + LIST [6] { elements: { - COMPREHENSION [11] { - iter_var: @c:0 - iter_range: { - IDENT [12] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [13] { value: false } - } - loop_condition: { - CALL [14] { - function: @not_strictly_false - args: { - CALL [15] { - function: !_ - args: { - IDENT [16] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [17] { - function: _||_ - args: { - IDENT [18] { - name: @x:0 - } - CALL [19] { - function: _>_ - args: { - IDENT [20] { - name: @c:0 - } - CONSTANT [21] { value: 0 } - } - } - } - } - } - result: { - IDENT [22] { - name: @x:0 - } - } - } + CONSTANT [7] { value: 1 } } } } - } - CALL [23] { - function: size - args: { - LIST [24] { - elements: { - COMPREHENSION [25] { - iter_var: @c:1 - iter_range: { - IDENT [26] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [27] { value: false } - } - loop_condition: { - CALL [28] { - function: @not_strictly_false - args: { - CALL [29] { - function: !_ - args: { - IDENT [30] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [31] { - function: _||_ - args: { - IDENT [32] { - name: @x:1 - } - CALL [33] { - function: _>_ - args: { - IDENT [34] { - name: @c:1 - } - CONSTANT [35] { value: 0 } - } - } - } - } - } - result: { - IDENT [36] { - name: @x:1 - } - } - } - } - } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [8] { value: false } } - } - } - } - CALL [37] { - function: size - args: { - LIST [38] { - elements: { - COMPREHENSION [39] { - iter_var: @c:2 - iter_range: { - IDENT [40] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [41] { value: false } - } - loop_condition: { - CALL [42] { - function: @not_strictly_false - args: { - CALL [43] { - function: !_ - args: { - IDENT [44] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [45] { - function: _||_ + loop_condition: { + CALL [9] { + function: @not_strictly_false + args: { + CALL [10] { + function: !_ args: { - IDENT [46] { - name: @x:2 - } - CALL [47] { - function: _>_ - args: { - IDENT [48] { - name: @c:2 - } - CONSTANT [49] { value: 1 } - } + IDENT [11] { + name: @ac:0:0 } } } } - result: { - IDENT [50] { - name: @x:2 - } - } } } - } - } - } - } - } - } - } - CALL [51] { - function: _==_ - args: { - CALL [52] { - function: _+_ - args: { - IDENT [53] { - name: @index2 - } - CALL [54] { - function: size - args: { - LIST [55] { - elements: { - COMPREHENSION [56] { - iter_var: @c:3 - iter_range: { - IDENT [57] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [58] { value: false } - } - loop_condition: { - CALL [59] { - function: @not_strictly_false - args: { - CALL [60] { - function: !_ - args: { - IDENT [61] { - name: @x:3 - } - } - } - } + loop_step: { + CALL [12] { + function: _||_ + args: { + IDENT [13] { + name: @ac:0:0 } - } - loop_step: { - CALL [62] { - function: _||_ + CALL [14] { + function: _>_ args: { - IDENT [63] { - name: @x:3 - } - CALL [64] { - function: _>_ - args: { - IDENT [65] { - name: @c:3 - } - CONSTANT [66] { value: 1 } - } + IDENT [15] { + name: @it:0:0 } + CONSTANT [16] { value: 0 } } } } - result: { - IDENT [67] { - name: @x:3 - } - } + } + } + result: { + IDENT [17] { + name: @ac:0:0 } } } @@ -1415,229 +1204,33 @@ CALL [1] { } } } - CONSTANT [68] { value: 4 } - } - } - } -} -Test case: MULTIPLE_MACROS_2 -Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] -=====> -CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - CALL [7] { - function: _+_ + CALL [18] { + function: size args: { - CALL [8] { - function: _+_ - args: { - CALL [9] { - function: _+_ - args: { - LIST [10] { - elements: { - COMPREHENSION [11] { - iter_var: @c:0 - iter_range: { - IDENT [12] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [13] { value: false } - } - loop_condition: { - CALL [14] { - function: @not_strictly_false - args: { - CALL [15] { - function: !_ - args: { - IDENT [16] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [17] { - function: _||_ - args: { - IDENT [18] { - name: @x:0 - } - CALL [19] { - function: _>_ - args: { - IDENT [20] { - name: @c:0 - } - CONSTANT [21] { value: 0 } - } - } - } - } - } - result: { - IDENT [22] { - name: @x:0 - } - } - } - } - } - LIST [23] { - elements: { - COMPREHENSION [24] { - iter_var: @c:1 - iter_range: { - IDENT [25] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [26] { value: false } - } - loop_condition: { - CALL [27] { - function: @not_strictly_false - args: { - CALL [28] { - function: !_ - args: { - IDENT [29] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [30] { - function: _||_ - args: { - IDENT [31] { - name: @x:1 - } - CALL [32] { - function: _>_ - args: { - IDENT [33] { - name: @c:1 - } - CONSTANT [34] { value: 0 } - } - } - } - } - } - result: { - IDENT [35] { - name: @x:1 - } - } - } - } - } - } - } - LIST [36] { - elements: { - COMPREHENSION [37] { - iter_var: @c:2 - iter_range: { - IDENT [38] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [39] { value: false } - } - loop_condition: { - CALL [40] { - function: @not_strictly_false - args: { - CALL [41] { - function: !_ - args: { - IDENT [42] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [43] { - function: _||_ - args: { - IDENT [44] { - name: @x:2 - } - CALL [45] { - function: _==_ - args: { - IDENT [46] { - name: @c:2 - } - CONSTANT [47] { value: "a" } - } - } - } - } - } - result: { - IDENT [48] { - name: @x:2 - } - } - } - } - } - } - } - LIST [49] { + LIST [19] { elements: { - COMPREHENSION [50] { - iter_var: @c:3 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [51] { - name: @index1 + LIST [21] { + elements: { + CONSTANT [22] { value: 2 } + } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [52] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [53] { + CALL [24] { function: @not_strictly_false args: { - CALL [54] { + CALL [25] { function: !_ args: { - IDENT [55] { - name: @x:3 + IDENT [26] { + name: @ac:0:0 } } } @@ -1645,27 +1238,27 @@ CALL [1] { } } loop_step: { - CALL [56] { + CALL [27] { function: _||_ args: { - IDENT [57] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } - CALL [58] { - function: _==_ + CALL [29] { + function: _>_ args: { - IDENT [59] { - name: @c:3 + IDENT [30] { + name: @it:0:0 } - CONSTANT [60] { value: "a" } + CONSTANT [31] { value: 1 } } } } } } result: { - IDENT [61] { - name: @x:3 + IDENT [32] { + name: @ac:0:0 } } } @@ -1675,65 +1268,73 @@ CALL [1] { } } } - CALL [62] { + CALL [33] { function: _==_ args: { - IDENT [63] { - name: @index2 - } - LIST [64] { - elements: { - CONSTANT [65] { value: true } - CONSTANT [66] { value: true } - CONSTANT [67] { value: true } - CONSTANT [68] { value: true } + CALL [34] { + function: _+_ + args: { + CALL [35] { + function: _+_ + args: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @index0 + } + IDENT [38] { + name: @index0 + } + } + } + IDENT [39] { + name: @index1 + } + } + } + IDENT [40] { + name: @index1 + } } } + CONSTANT [41] { value: 4 } } } } } -Test case: MULTIPLE_MACROS_3 -Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - } - } - CALL [5] { - function: _&&_ - args: { - CALL [6] { - function: _&&_ - args: { - COMPREHENSION [7] { - iter_var: @c:0 + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + COMPREHENSION [4] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [10] { + CALL [8] { function: @not_strictly_false args: { - CALL [11] { + CALL [9] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1741,38 +1342,44 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [11] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [15] { + CALL [13] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + } + } + LIST [17] { + elements: { + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { CONSTANT [21] { value: false } } @@ -1784,7 +1391,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:1 } } } @@ -1796,15 +1403,15 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:1 } CALL [27] { - function: _>_ + function: _==_ args: { IDENT [28] { - name: @c:1 + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [29] { value: "a" } } } } @@ -1812,35 +1419,175 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:1 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + CALL [32] { + function: _+_ + args: { + CALL [33] { + function: _+_ + args: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @index0 + } + IDENT [36] { + name: @index0 + } + } + } + IDENT [37] { + name: @index1 + } + } + } + IDENT [38] { + name: @index1 + } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [31] { + } + } + CALL [21] { + function: _&&_ + args: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @index0 + } + IDENT [24] { + name: @index0 + } + } + } + CALL [25] { function: _&&_ args: { - COMPREHENSION [32] { - iter_var: @c:2 + COMPREHENSION [26] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 + LIST [27] { + elements: { + CONSTANT [28] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [34] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [35] { + CALL [30] { function: @not_strictly_false args: { - CALL [36] { + CALL [31] { function: !_ args: { - IDENT [37] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1848,52 +1595,38 @@ CALL [1] { } } loop_step: { - CALL [38] { - function: _||_ - args: { - IDENT [39] { - name: @x:2 - } - CALL [40] { - function: _>_ - args: { - IDENT [41] { - name: @c:2 - } - CONSTANT [42] { value: 1 } - } - } - } + IDENT [33] { + name: @index1 } } result: { - IDENT [43] { - name: @x:2 + IDENT [34] { + name: @ac:0:0 } } } - COMPREHENSION [44] { - iter_var: @c:3 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - LIST [45] { + LIST [36] { elements: { - CONSTANT [46] { value: 2 } + CONSTANT [37] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [47] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [48] { + CALL [39] { function: @not_strictly_false args: { - CALL [49] { + CALL [40] { function: !_ args: { - IDENT [50] { - name: @x:3 + IDENT [41] { + name: @ac:0:0 } } } @@ -1901,27 +1634,13 @@ CALL [1] { } } loop_step: { - CALL [51] { - function: _||_ - args: { - IDENT [52] { - name: @x:3 - } - CALL [53] { - function: _>_ - args: { - IDENT [54] { - name: @c:3 - } - CONSTANT [55] { value: 1 } - } - } - } + IDENT [42] { + name: @index1 } } result: { - IDENT [56] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -1954,13 +1673,13 @@ CALL [1] { } } COMPREHENSION [11] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [12] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [13] { elements: { @@ -1975,18 +1694,18 @@ CALL [1] { function: _+_ args: { IDENT [16] { - name: @x:1 + name: @ac:0:0 } LIST [17] { elements: { COMPREHENSION [18] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [19] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [20] { elements: { @@ -2001,7 +1720,7 @@ CALL [1] { function: _+_ args: { IDENT [23] { - name: @x:0 + name: @ac:1:0 } LIST [24] { elements: { @@ -2009,7 +1728,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @c:0 + name: @it:1:0 } CONSTANT [27] { value: 1 } } @@ -2021,7 +1740,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:1:0 } } } @@ -2032,7 +1751,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } } } @@ -2070,7 +1789,7 @@ CALL [1] { LIST [2] { elements: { COMPREHENSION [3] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [4] { elements: { @@ -2079,7 +1798,7 @@ CALL [1] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [7] { elements: { @@ -2094,12 +1813,12 @@ CALL [1] { function: _+_ args: { IDENT [10] { - name: @x:1 + name: @ac:0:0 } LIST [11] { elements: { COMPREHENSION [12] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [13] { elements: { @@ -2109,7 +1828,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [17] { elements: { @@ -2127,10 +1846,10 @@ CALL [1] { function: _==_ args: { IDENT [21] { - name: @c:0 + name: @it:1:0 } IDENT [22] { - name: @c:1 + name: @it:0:0 } } } @@ -2138,26 +1857,26 @@ CALL [1] { function: _+_ args: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } LIST [25] { elements: { IDENT [26] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [27] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [28] { - name: @x:0 + name: @ac:1:0 } } } @@ -2168,7 +1887,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } } } @@ -2206,155 +1925,73 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - COMPREHENSION [7] { - iter_var: @c:1 + COMPREHENSION [3] { + iter_var: @it:0:0 iter_range: { - IDENT [8] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [9] { + LIST [4] { elements: { + CONSTANT [5] { value: 1 } + CONSTANT [6] { value: 2 } + CONSTANT [7] { value: 3 } } } } - loop_condition: { - CONSTANT [10] { value: true } - } - loop_step: { - CALL [11] { - function: _+_ - args: { - IDENT [12] { - name: @x:1 - } - LIST [13] { - elements: { - COMPREHENSION [14] { - iter_var: @c:0 - iter_range: { - IDENT [15] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [16] { - elements: { - } - } - } - loop_condition: { - CONSTANT [17] { value: true } - } - loop_step: { - CALL [18] { - function: _+_ - args: { - IDENT [19] { - name: @x:0 - } - LIST [20] { - elements: { - CALL [21] { - function: _+_ - args: { - IDENT [22] { - name: @c:0 - } - CONSTANT [23] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [24] { - name: @x:0 - } - } - } - } - } - } - } - } - result: { - IDENT [25] { - name: @x:1 - } - } - } - COMPREHENSION [26] { - iter_var: @c:3 - iter_range: { - IDENT [27] { - name: @index0 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [28] { + LIST [8] { elements: { } } } loop_condition: { - CONSTANT [29] { value: true } + CONSTANT [9] { value: true } } loop_step: { - CALL [30] { + CALL [10] { function: _+_ args: { - IDENT [31] { - name: @x:3 + IDENT [11] { + name: @ac:0:0 } - LIST [32] { + LIST [12] { elements: { - COMPREHENSION [33] { - iter_var: @c:2 + COMPREHENSION [13] { + iter_var: @it:1:0 iter_range: { - IDENT [34] { - name: @index0 + LIST [14] { + elements: { + CONSTANT [15] { value: 1 } + CONSTANT [16] { value: 2 } + CONSTANT [17] { value: 3 } + } } } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [35] { + LIST [18] { elements: { } } } loop_condition: { - CONSTANT [36] { value: true } + CONSTANT [19] { value: true } } loop_step: { - CALL [37] { + CALL [20] { function: _+_ args: { - IDENT [38] { - name: @x:2 + IDENT [21] { + name: @ac:1:0 } - LIST [39] { + LIST [22] { elements: { - CALL [40] { + CALL [23] { function: _+_ args: { - IDENT [41] { - name: @c:2 + IDENT [24] { + name: @it:1:0 } - CONSTANT [42] { value: 1 } + CONSTANT [25] { value: 1 } } } } @@ -2363,8 +2000,8 @@ CALL [1] { } } result: { - IDENT [43] { - name: @x:2 + IDENT [26] { + name: @ac:1:0 } } } @@ -2374,21 +2011,21 @@ CALL [1] { } } result: { - IDENT [44] { - name: @x:3 + IDENT [27] { + name: @ac:0:0 } } } } } - CALL [45] { + CALL [28] { function: _==_ args: { - IDENT [46] { - name: @index1 + IDENT [29] { + name: @index0 } - IDENT [47] { - name: @index2 + IDENT [30] { + name: @index0 } } } @@ -2559,13 +2196,13 @@ CALL [1] { } } COMPREHENSION [13] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [14] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [15] { elements: { @@ -2580,18 +2217,18 @@ CALL [1] { function: _+_ args: { IDENT [18] { - name: @x:1 + name: @ac:0:0 } LIST [19] { elements: { COMPREHENSION [20] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [21] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [22] { elements: { @@ -2606,7 +2243,7 @@ CALL [1] { function: _+_ args: { IDENT [25] { - name: @x:0 + name: @ac:1:0 } LIST [26] { elements: { @@ -2623,7 +2260,7 @@ CALL [1] { } result: { IDENT [30] { - name: @x:0 + name: @ac:1:0 } } } @@ -2634,7 +2271,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } @@ -2689,7 +2326,7 @@ CALL [1] { function: _||_ args: { COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [10] { elements: { @@ -2714,7 +2351,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [17] { value: false } } @@ -2726,7 +2363,7 @@ CALL [1] { function: !_ args: { IDENT [20] { - name: @x:0 + name: @ac:0:0 } } } @@ -2738,7 +2375,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } CALL [23] { function: _>_ @@ -2747,7 +2384,7 @@ CALL [1] { function: _-_ args: { IDENT [25] { - name: @c:0 + name: @it:0:0 } CONSTANT [26] { value: 1 } } @@ -2760,7 +2397,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:0:0 } } } @@ -2783,10 +2420,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2794,20 +2431,20 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } } } COMPREHENSION [9] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [11] { elements: { @@ -2816,7 +2453,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2831,7 +2468,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2852,12 +2489,12 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -2872,7 +2509,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2893,7 +2530,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline index 9da40d283..fd78a51a9 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline @@ -1142,507 +1142,95 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - CALL [7] { - function: _+_ + CALL [3] { + function: size args: { - CALL [8] { - function: _+_ - args: { - CALL [9] { - function: _+_ - args: { - CALL [10] { - function: size - args: { - LIST [11] { - elements: { - COMPREHENSION [12] { - iter_var: @c:0 - iter_range: { - IDENT [13] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [14] { value: false } - } - loop_condition: { - CALL [15] { - function: @not_strictly_false - args: { - CALL [16] { - function: !_ - args: { - IDENT [17] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [18] { - function: _||_ - args: { - IDENT [19] { - name: @x:0 - } - CALL [20] { - function: _>_ - args: { - IDENT [21] { - name: @c:0 - } - CONSTANT [22] { value: 0 } - } - } - } - } - } - result: { - IDENT [23] { - name: @x:0 - } - } - } - } - } - } - } - CALL [24] { - function: size - args: { - LIST [25] { - elements: { - COMPREHENSION [26] { - iter_var: @c:1 - iter_range: { - IDENT [27] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [28] { value: false } - } - loop_condition: { - CALL [29] { - function: @not_strictly_false - args: { - CALL [30] { - function: !_ - args: { - IDENT [31] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [32] { - function: _||_ - args: { - IDENT [33] { - name: @x:1 - } - CALL [34] { - function: _>_ - args: { - IDENT [35] { - name: @c:1 - } - CONSTANT [36] { value: 0 } - } - } - } - } - } - result: { - IDENT [37] { - name: @x:1 - } - } - } - } - } - } - } - } - } - CALL [38] { - function: size - args: { - LIST [39] { + LIST [4] { + elements: { + COMPREHENSION [5] { + iter_var: @it:0:0 + iter_range: { + LIST [6] { elements: { - COMPREHENSION [40] { - iter_var: @c:2 - iter_range: { - IDENT [41] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [42] { value: false } - } - loop_condition: { - CALL [43] { - function: @not_strictly_false - args: { - CALL [44] { - function: !_ - args: { - IDENT [45] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [46] { - function: _||_ - args: { - IDENT [47] { - name: @x:2 - } - CALL [48] { - function: _>_ - args: { - IDENT [49] { - name: @c:2 - } - CONSTANT [50] { value: 1 } - } - } - } - } - } - result: { - IDENT [51] { - name: @x:2 - } - } - } + CONSTANT [7] { value: 1 } } } } - } - } - } - CALL [52] { - function: size - args: { - LIST [53] { - elements: { - COMPREHENSION [54] { - iter_var: @c:3 - iter_range: { - IDENT [55] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [56] { value: false } - } - loop_condition: { - CALL [57] { - function: @not_strictly_false - args: { - CALL [58] { - function: !_ - args: { - IDENT [59] { - name: @x:3 - } - } - } - } - } - } - loop_step: { - CALL [60] { - function: _||_ + accu_var: @ac:0:0 + accu_init: { + CONSTANT [8] { value: false } + } + loop_condition: { + CALL [9] { + function: @not_strictly_false + args: { + CALL [10] { + function: !_ args: { - IDENT [61] { - name: @x:3 - } - CALL [62] { - function: _>_ - args: { - IDENT [63] { - name: @c:3 - } - CONSTANT [64] { value: 1 } - } + IDENT [11] { + name: @ac:0:0 } } } } - result: { - IDENT [65] { - name: @x:3 - } - } } } - } - } - } - } - } - } - } - CALL [66] { - function: _==_ - args: { - IDENT [67] { - name: @index2 - } - CONSTANT [68] { value: 4 } - } - } - } -} -Test case: MULTIPLE_MACROS_2 -Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] -=====> -CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - } - } - CALL [7] { - function: _==_ - args: { - CALL [8] { - function: _+_ - args: { - CALL [9] { - function: _+_ - args: { - CALL [10] { - function: _+_ - args: { - LIST [11] { - elements: { - COMPREHENSION [12] { - iter_var: @c:0 - iter_range: { - IDENT [13] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [14] { value: false } - } - loop_condition: { - CALL [15] { - function: @not_strictly_false - args: { - CALL [16] { - function: !_ - args: { - IDENT [17] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [18] { - function: _||_ - args: { - IDENT [19] { - name: @x:0 - } - CALL [20] { - function: _>_ - args: { - IDENT [21] { - name: @c:0 - } - CONSTANT [22] { value: 0 } - } - } - } - } - } - result: { - IDENT [23] { - name: @x:0 - } - } + loop_step: { + CALL [12] { + function: _||_ + args: { + IDENT [13] { + name: @ac:0:0 } - } - } - LIST [24] { - elements: { - COMPREHENSION [25] { - iter_var: @c:1 - iter_range: { - IDENT [26] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [27] { value: false } - } - loop_condition: { - CALL [28] { - function: @not_strictly_false - args: { - CALL [29] { - function: !_ - args: { - IDENT [30] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [31] { - function: _||_ - args: { - IDENT [32] { - name: @x:1 - } - CALL [33] { - function: _>_ - args: { - IDENT [34] { - name: @c:1 - } - CONSTANT [35] { value: 0 } - } - } - } - } - } - result: { - IDENT [36] { - name: @x:1 + CALL [14] { + function: _>_ + args: { + IDENT [15] { + name: @it:0:0 } + CONSTANT [16] { value: 0 } } } } } } - } - LIST [37] { - elements: { - COMPREHENSION [38] { - iter_var: @c:2 - iter_range: { - IDENT [39] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [40] { value: false } - } - loop_condition: { - CALL [41] { - function: @not_strictly_false - args: { - CALL [42] { - function: !_ - args: { - IDENT [43] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [44] { - function: _||_ - args: { - IDENT [45] { - name: @x:2 - } - CALL [46] { - function: _==_ - args: { - IDENT [47] { - name: @c:2 - } - CONSTANT [48] { value: "a" } - } - } - } - } - } - result: { - IDENT [49] { - name: @x:2 - } - } + result: { + IDENT [17] { + name: @ac:0:0 } } } } } - LIST [50] { + } + } + CALL [18] { + function: size + args: { + LIST [19] { elements: { - COMPREHENSION [51] { - iter_var: @c:3 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [52] { - name: @index1 + LIST [21] { + elements: { + CONSTANT [22] { value: 2 } + } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [53] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [54] { + CALL [24] { function: @not_strictly_false args: { - CALL [55] { + CALL [25] { function: !_ args: { - IDENT [56] { - name: @x:3 + IDENT [26] { + name: @ac:0:0 } } } @@ -1650,27 +1238,27 @@ CALL [1] { } } loop_step: { - CALL [57] { + CALL [27] { function: _||_ args: { - IDENT [58] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } - CALL [59] { - function: _==_ + CALL [29] { + function: _>_ args: { - IDENT [60] { - name: @c:3 + IDENT [30] { + name: @it:0:0 } - CONSTANT [61] { value: "a" } + CONSTANT [31] { value: 1 } } } } } } result: { - IDENT [62] { - name: @x:3 + IDENT [32] { + name: @ac:0:0 } } } @@ -1678,20 +1266,45 @@ CALL [1] { } } } - LIST [63] { - elements: { - CONSTANT [64] { value: true } - CONSTANT [65] { value: true } - CONSTANT [66] { value: true } - CONSTANT [67] { value: true } + } + } + CALL [33] { + function: _==_ + args: { + CALL [34] { + function: _+_ + args: { + CALL [35] { + function: _+_ + args: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @index0 + } + IDENT [38] { + name: @index0 + } + } + } + IDENT [39] { + name: @index1 + } + } + } + IDENT [40] { + name: @index1 + } } } + CONSTANT [41] { value: 4 } } } } } -Test case: MULTIPLE_MACROS_3 -Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> CALL [1] { function: cel.@block @@ -1700,37 +1313,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - } - } - CALL [5] { - function: _&&_ - args: { - CALL [6] { - function: _&&_ - args: { - COMPREHENSION [7] { - iter_var: @c:0 - iter_range: { - IDENT [8] { - name: @index0 + COMPREHENSION [4] { + iter_var: @it:0:0 + iter_range: { + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [10] { + CALL [8] { function: @not_strictly_false args: { - CALL [11] { + CALL [9] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1738,38 +1342,44 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [11] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [15] { + CALL [13] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + } + } + LIST [17] { + elements: { + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { CONSTANT [21] { value: false } } @@ -1781,7 +1391,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:1 } } } @@ -1793,15 +1403,15 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:1 } CALL [27] { - function: _>_ + function: _==_ args: { IDENT [28] { - name: @c:1 + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [29] { value: "a" } } } } @@ -1809,35 +1419,175 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:1 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + CALL [32] { + function: _+_ + args: { + CALL [33] { + function: _+_ + args: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @index0 + } + IDENT [36] { + name: @index0 + } + } + } + IDENT [37] { + name: @index1 + } + } + } + IDENT [38] { + name: @index1 + } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [31] { + } + } + CALL [21] { + function: _&&_ + args: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @index0 + } + IDENT [24] { + name: @index0 + } + } + } + CALL [25] { function: _&&_ args: { - COMPREHENSION [32] { - iter_var: @c:2 + COMPREHENSION [26] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 + LIST [27] { + elements: { + CONSTANT [28] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [34] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [35] { + CALL [30] { function: @not_strictly_false args: { - CALL [36] { + CALL [31] { function: !_ args: { - IDENT [37] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1845,52 +1595,38 @@ CALL [1] { } } loop_step: { - CALL [38] { - function: _||_ - args: { - IDENT [39] { - name: @x:2 - } - CALL [40] { - function: _>_ - args: { - IDENT [41] { - name: @c:2 - } - CONSTANT [42] { value: 1 } - } - } - } + IDENT [33] { + name: @index1 } } result: { - IDENT [43] { - name: @x:2 + IDENT [34] { + name: @ac:0:0 } } } - COMPREHENSION [44] { - iter_var: @c:3 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - LIST [45] { + LIST [36] { elements: { - CONSTANT [46] { value: 2 } + CONSTANT [37] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [47] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [48] { + CALL [39] { function: @not_strictly_false args: { - CALL [49] { + CALL [40] { function: !_ args: { - IDENT [50] { - name: @x:3 + IDENT [41] { + name: @ac:0:0 } } } @@ -1898,27 +1634,13 @@ CALL [1] { } } loop_step: { - CALL [51] { - function: _||_ - args: { - IDENT [52] { - name: @x:3 - } - CALL [53] { - function: _>_ - args: { - IDENT [54] { - name: @c:3 - } - CONSTANT [55] { value: 1 } - } - } - } + IDENT [42] { + name: @index1 } } result: { - IDENT [56] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -1956,13 +1678,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [12] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [13] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [14] { elements: { @@ -1977,18 +1699,18 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:1 + name: @ac:0:0 } LIST [18] { elements: { COMPREHENSION [19] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [20] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [21] { elements: { @@ -2003,7 +1725,7 @@ CALL [1] { function: _+_ args: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } LIST [25] { elements: { @@ -2011,7 +1733,7 @@ CALL [1] { function: _+_ args: { IDENT [27] { - name: @c:0 + name: @it:1:0 } CONSTANT [28] { value: 1 } } @@ -2023,7 +1745,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:0 + name: @ac:1:0 } } } @@ -2034,7 +1756,7 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:0 } } } @@ -2062,7 +1784,7 @@ CALL [31] { function: _==_ args: { COMPREHENSION [30] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [1] { elements: { @@ -2071,7 +1793,7 @@ CALL [31] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [24] { elements: { @@ -2086,12 +1808,12 @@ CALL [31] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { COMPREHENSION [23] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [6] { elements: { @@ -2101,7 +1823,7 @@ CALL [31] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [15] { elements: { @@ -2119,10 +1841,10 @@ CALL [31] { function: _==_ args: { IDENT [12] { - name: @c:0 + name: @it:1:0 } IDENT [14] { - name: @c:1 + name: @it:0:0 } } } @@ -2130,26 +1852,26 @@ CALL [31] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { IDENT [11] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [20] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -2160,7 +1882,7 @@ CALL [31] { } result: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } } } @@ -2188,160 +1910,73 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - } - } - CALL [7] { - function: _==_ - args: { - COMPREHENSION [8] { - iter_var: @c:1 + COMPREHENSION [3] { + iter_var: @it:0:0 iter_range: { - IDENT [9] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [10] { + LIST [4] { elements: { + CONSTANT [5] { value: 1 } + CONSTANT [6] { value: 2 } + CONSTANT [7] { value: 3 } } } } - loop_condition: { - CONSTANT [11] { value: true } - } - loop_step: { - CALL [12] { - function: _+_ - args: { - IDENT [13] { - name: @x:1 - } - LIST [14] { - elements: { - COMPREHENSION [15] { - iter_var: @c:0 - iter_range: { - IDENT [16] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [17] { - elements: { - } - } - } - loop_condition: { - CONSTANT [18] { value: true } - } - loop_step: { - CALL [19] { - function: _+_ - args: { - IDENT [20] { - name: @x:0 - } - LIST [21] { - elements: { - CALL [22] { - function: _+_ - args: { - IDENT [23] { - name: @c:0 - } - CONSTANT [24] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [25] { - name: @x:0 - } - } - } - } - } - } - } - } - result: { - IDENT [26] { - name: @x:1 - } - } - } - COMPREHENSION [27] { - iter_var: @c:3 - iter_range: { - IDENT [28] { - name: @index0 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [29] { + LIST [8] { elements: { } } } loop_condition: { - CONSTANT [30] { value: true } + CONSTANT [9] { value: true } } loop_step: { - CALL [31] { + CALL [10] { function: _+_ args: { - IDENT [32] { - name: @x:3 + IDENT [11] { + name: @ac:0:0 } - LIST [33] { + LIST [12] { elements: { - COMPREHENSION [34] { - iter_var: @c:2 + COMPREHENSION [13] { + iter_var: @it:1:0 iter_range: { - IDENT [35] { - name: @index0 + LIST [14] { + elements: { + CONSTANT [15] { value: 1 } + CONSTANT [16] { value: 2 } + CONSTANT [17] { value: 3 } + } } } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [36] { + LIST [18] { elements: { } } } loop_condition: { - CONSTANT [37] { value: true } + CONSTANT [19] { value: true } } loop_step: { - CALL [38] { + CALL [20] { function: _+_ args: { - IDENT [39] { - name: @x:2 + IDENT [21] { + name: @ac:1:0 } - LIST [40] { + LIST [22] { elements: { - CALL [41] { + CALL [23] { function: _+_ args: { - IDENT [42] { - name: @c:2 + IDENT [24] { + name: @it:1:0 } - CONSTANT [43] { value: 1 } + CONSTANT [25] { value: 1 } } } } @@ -2350,8 +1985,8 @@ CALL [1] { } } result: { - IDENT [44] { - name: @x:2 + IDENT [26] { + name: @ac:1:0 } } } @@ -2361,13 +1996,24 @@ CALL [1] { } } result: { - IDENT [45] { - name: @x:3 + IDENT [27] { + name: @ac:0:0 } } } } } + CALL [28] { + function: _==_ + args: { + IDENT [29] { + name: @index0 + } + IDENT [30] { + name: @index0 + } + } + } } } Test case: INCLUSION_LIST @@ -2540,13 +2186,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [14] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [15] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [16] { elements: { @@ -2561,18 +2207,18 @@ CALL [1] { function: _+_ args: { IDENT [19] { - name: @x:1 + name: @ac:0:0 } LIST [20] { elements: { COMPREHENSION [21] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [22] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [23] { elements: { @@ -2587,7 +2233,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:0 + name: @ac:1:0 } LIST [27] { elements: { @@ -2604,7 +2250,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:0 + name: @ac:1:0 } } } @@ -2615,7 +2261,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } } } @@ -2662,7 +2308,7 @@ CALL [1] { function: _||_ args: { COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [10] { elements: { @@ -2687,7 +2333,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [17] { value: false } } @@ -2699,7 +2345,7 @@ CALL [1] { function: !_ args: { IDENT [20] { - name: @x:0 + name: @ac:0:0 } } } @@ -2711,7 +2357,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } CALL [23] { function: _>_ @@ -2720,7 +2366,7 @@ CALL [1] { function: _-_ args: { IDENT [25] { - name: @c:0 + name: @it:0:0 } CONSTANT [26] { value: 1 } } @@ -2733,7 +2379,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:0:0 } } } @@ -2756,10 +2402,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2767,20 +2413,20 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } } } COMPREHENSION [9] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [11] { elements: { @@ -2789,7 +2435,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2804,7 +2450,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2825,12 +2471,12 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -2845,7 +2491,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2866,7 +2512,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline index 025cd4769..b273bd6f2 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline @@ -1130,504 +1130,95 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: 2 } - } - } - } - } - CALL [7] { - function: _==_ - args: { - CALL [8] { - function: _+_ + CALL [3] { + function: size args: { - CALL [9] { - function: _+_ - args: { - CALL [10] { - function: _+_ - args: { - CALL [11] { - function: size - args: { - LIST [12] { - elements: { - COMPREHENSION [13] { - iter_var: @c:0 - iter_range: { - IDENT [14] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [15] { value: false } - } - loop_condition: { - CALL [16] { - function: @not_strictly_false - args: { - CALL [17] { - function: !_ - args: { - IDENT [18] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [19] { - function: _||_ - args: { - IDENT [20] { - name: @x:0 - } - CALL [21] { - function: _>_ - args: { - IDENT [22] { - name: @c:0 - } - CONSTANT [23] { value: 0 } - } - } - } - } - } - result: { - IDENT [24] { - name: @x:0 - } - } - } - } - } - } - } - CALL [25] { - function: size - args: { - LIST [26] { - elements: { - COMPREHENSION [27] { - iter_var: @c:1 - iter_range: { - IDENT [28] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [29] { value: false } - } - loop_condition: { - CALL [30] { - function: @not_strictly_false - args: { - CALL [31] { - function: !_ - args: { - IDENT [32] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [33] { - function: _||_ - args: { - IDENT [34] { - name: @x:1 - } - CALL [35] { - function: _>_ - args: { - IDENT [36] { - name: @c:1 - } - CONSTANT [37] { value: 0 } - } - } - } - } - } - result: { - IDENT [38] { - name: @x:1 - } - } - } - } - } - } - } - } - } - CALL [39] { - function: size - args: { - LIST [40] { + LIST [4] { + elements: { + COMPREHENSION [5] { + iter_var: @it:0:0 + iter_range: { + LIST [6] { elements: { - COMPREHENSION [41] { - iter_var: @c:2 - iter_range: { - IDENT [42] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [43] { value: false } - } - loop_condition: { - CALL [44] { - function: @not_strictly_false - args: { - CALL [45] { - function: !_ - args: { - IDENT [46] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [47] { - function: _||_ - args: { - IDENT [48] { - name: @x:2 - } - CALL [49] { - function: _>_ - args: { - IDENT [50] { - name: @c:2 - } - CONSTANT [51] { value: 1 } - } - } - } - } - } - result: { - IDENT [52] { - name: @x:2 - } - } - } + CONSTANT [7] { value: 1 } } } } - } - } - } - CALL [53] { - function: size - args: { - LIST [54] { - elements: { - COMPREHENSION [55] { - iter_var: @c:3 - iter_range: { - IDENT [56] { - name: @index1 - } - } - accu_var: @x:3 - accu_init: { - CONSTANT [57] { value: false } - } - loop_condition: { - CALL [58] { - function: @not_strictly_false + accu_var: @ac:0:0 + accu_init: { + CONSTANT [8] { value: false } + } + loop_condition: { + CALL [9] { + function: @not_strictly_false + args: { + CALL [10] { + function: !_ args: { - CALL [59] { - function: !_ - args: { - IDENT [60] { - name: @x:3 - } - } + IDENT [11] { + name: @ac:0:0 } } } } - loop_step: { - CALL [61] { - function: _||_ - args: { - IDENT [62] { - name: @x:3 - } - CALL [63] { - function: _>_ - args: { - IDENT [64] { - name: @c:3 - } - CONSTANT [65] { value: 1 } - } - } - } - } - } - result: { - IDENT [66] { - name: @x:3 - } - } } } - } - } - } - } - } - CONSTANT [67] { value: 4 } - } - } - } -} -Test case: MULTIPLE_MACROS_2 -Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] -=====> -CALL [1] { - function: cel.@block - args: { - LIST [2] { - elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - } - } - LIST [5] { - elements: { - CONSTANT [6] { value: "a" } - } - } - } - } - CALL [7] { - function: _==_ - args: { - CALL [8] { - function: _+_ - args: { - CALL [9] { - function: _+_ - args: { - CALL [10] { - function: _+_ - args: { - LIST [11] { - elements: { - COMPREHENSION [12] { - iter_var: @c:0 - iter_range: { - IDENT [13] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - CONSTANT [14] { value: false } - } - loop_condition: { - CALL [15] { - function: @not_strictly_false - args: { - CALL [16] { - function: !_ - args: { - IDENT [17] { - name: @x:0 - } - } - } - } - } - } - loop_step: { - CALL [18] { - function: _||_ - args: { - IDENT [19] { - name: @x:0 - } - CALL [20] { - function: _>_ - args: { - IDENT [21] { - name: @c:0 - } - CONSTANT [22] { value: 0 } - } - } - } - } - } - result: { - IDENT [23] { - name: @x:0 - } - } + loop_step: { + CALL [12] { + function: _||_ + args: { + IDENT [13] { + name: @ac:0:0 } - } - } - LIST [24] { - elements: { - COMPREHENSION [25] { - iter_var: @c:1 - iter_range: { - IDENT [26] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - CONSTANT [27] { value: false } - } - loop_condition: { - CALL [28] { - function: @not_strictly_false - args: { - CALL [29] { - function: !_ - args: { - IDENT [30] { - name: @x:1 - } - } - } - } - } - } - loop_step: { - CALL [31] { - function: _||_ - args: { - IDENT [32] { - name: @x:1 - } - CALL [33] { - function: _>_ - args: { - IDENT [34] { - name: @c:1 - } - CONSTANT [35] { value: 0 } - } - } - } - } - } - result: { - IDENT [36] { - name: @x:1 + CALL [14] { + function: _>_ + args: { + IDENT [15] { + name: @it:0:0 } + CONSTANT [16] { value: 0 } } } } } } - } - LIST [37] { - elements: { - COMPREHENSION [38] { - iter_var: @c:2 - iter_range: { - IDENT [39] { - name: @index1 - } - } - accu_var: @x:2 - accu_init: { - CONSTANT [40] { value: false } - } - loop_condition: { - CALL [41] { - function: @not_strictly_false - args: { - CALL [42] { - function: !_ - args: { - IDENT [43] { - name: @x:2 - } - } - } - } - } - } - loop_step: { - CALL [44] { - function: _||_ - args: { - IDENT [45] { - name: @x:2 - } - CALL [46] { - function: _==_ - args: { - IDENT [47] { - name: @c:2 - } - CONSTANT [48] { value: "a" } - } - } - } - } - } - result: { - IDENT [49] { - name: @x:2 - } - } + result: { + IDENT [17] { + name: @ac:0:0 } } } } } - LIST [50] { + } + } + CALL [18] { + function: size + args: { + LIST [19] { elements: { - COMPREHENSION [51] { - iter_var: @c:3 + COMPREHENSION [20] { + iter_var: @it:0:0 iter_range: { - IDENT [52] { - name: @index1 + LIST [21] { + elements: { + CONSTANT [22] { value: 2 } + } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [53] { value: false } + CONSTANT [23] { value: false } } loop_condition: { - CALL [54] { + CALL [24] { function: @not_strictly_false args: { - CALL [55] { + CALL [25] { function: !_ args: { - IDENT [56] { - name: @x:3 + IDENT [26] { + name: @ac:0:0 } } } @@ -1635,27 +1226,27 @@ CALL [1] { } } loop_step: { - CALL [57] { + CALL [27] { function: _||_ args: { - IDENT [58] { - name: @x:3 + IDENT [28] { + name: @ac:0:0 } - CALL [59] { - function: _==_ + CALL [29] { + function: _>_ args: { - IDENT [60] { - name: @c:3 + IDENT [30] { + name: @it:0:0 } - CONSTANT [61] { value: "a" } + CONSTANT [31] { value: 1 } } } } } } result: { - IDENT [62] { - name: @x:3 + IDENT [32] { + name: @ac:0:0 } } } @@ -1663,20 +1254,45 @@ CALL [1] { } } } - LIST [63] { - elements: { - CONSTANT [64] { value: true } - CONSTANT [65] { value: true } - CONSTANT [66] { value: true } - CONSTANT [67] { value: true } + } + } + CALL [33] { + function: _==_ + args: { + CALL [34] { + function: _+_ + args: { + CALL [35] { + function: _+_ + args: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @index0 + } + IDENT [38] { + name: @index0 + } + } + } + IDENT [39] { + name: @index1 + } + } + } + IDENT [40] { + name: @index1 + } } } + CONSTANT [41] { value: 4 } } } } } -Test case: MULTIPLE_MACROS_3 -Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> CALL [1] { function: cel.@block @@ -1685,37 +1301,28 @@ CALL [1] { elements: { LIST [3] { elements: { - CONSTANT [4] { value: 1 } - } - } - } - } - CALL [5] { - function: _&&_ - args: { - CALL [6] { - function: _&&_ - args: { - COMPREHENSION [7] { - iter_var: @c:0 - iter_range: { - IDENT [8] { - name: @index0 + COMPREHENSION [4] { + iter_var: @it:0:0 + iter_range: { + LIST [5] { + elements: { + CONSTANT [6] { value: 1 } + } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { - CONSTANT [9] { value: false } + CONSTANT [7] { value: false } } loop_condition: { - CALL [10] { + CALL [8] { function: @not_strictly_false args: { - CALL [11] { + CALL [9] { function: !_ args: { - IDENT [12] { - name: @x:0 + IDENT [10] { + name: @ac:0:0 } } } @@ -1723,38 +1330,44 @@ CALL [1] { } } loop_step: { - CALL [13] { + CALL [11] { function: _||_ args: { - IDENT [14] { - name: @x:0 + IDENT [12] { + name: @ac:0:0 } - CALL [15] { + CALL [13] { function: _>_ args: { - IDENT [16] { - name: @c:0 + IDENT [14] { + name: @it:0:0 } - CONSTANT [17] { value: 0 } + CONSTANT [15] { value: 0 } } } } } } result: { - IDENT [18] { - name: @x:0 + IDENT [16] { + name: @ac:0:0 } } } - COMPREHENSION [19] { - iter_var: @c:1 + } + } + LIST [17] { + elements: { + COMPREHENSION [18] { + iter_var: @it:0:1 iter_range: { - IDENT [20] { - name: @index0 + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } } } - accu_var: @x:1 + accu_var: @ac:0:1 accu_init: { CONSTANT [21] { value: false } } @@ -1766,7 +1379,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:1 + name: @ac:0:1 } } } @@ -1778,15 +1391,15 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:1 } CALL [27] { - function: _>_ + function: _==_ args: { IDENT [28] { - name: @c:1 + name: @it:0:1 } - CONSTANT [29] { value: 0 } + CONSTANT [29] { value: "a" } } } } @@ -1794,35 +1407,175 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:1 + } + } + } + } + } + } + } + CALL [31] { + function: _==_ + args: { + CALL [32] { + function: _+_ + args: { + CALL [33] { + function: _+_ + args: { + CALL [34] { + function: _+_ + args: { + IDENT [35] { + name: @index0 + } + IDENT [36] { + name: @index0 + } + } + } + IDENT [37] { + name: @index1 + } + } + } + IDENT [38] { + name: @index1 + } + } + } + LIST [39] { + elements: { + CONSTANT [40] { value: true } + CONSTANT [41] { value: true } + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: _||_ + args: { + IDENT [17] { + name: @ac:0:0 + } + CALL [18] { + function: _>_ + args: { + IDENT [19] { + name: @it:0:0 } + CONSTANT [20] { value: 1 } } } } } - CALL [31] { + } + } + CALL [21] { + function: _&&_ + args: { + CALL [22] { + function: _&&_ + args: { + IDENT [23] { + name: @index0 + } + IDENT [24] { + name: @index0 + } + } + } + CALL [25] { function: _&&_ args: { - COMPREHENSION [32] { - iter_var: @c:2 + COMPREHENSION [26] { + iter_var: @it:0:0 iter_range: { - IDENT [33] { - name: @index0 + LIST [27] { + elements: { + CONSTANT [28] { value: 1 } + } } } - accu_var: @x:2 + accu_var: @ac:0:0 accu_init: { - CONSTANT [34] { value: false } + CONSTANT [29] { value: false } } loop_condition: { - CALL [35] { + CALL [30] { function: @not_strictly_false args: { - CALL [36] { + CALL [31] { function: !_ args: { - IDENT [37] { - name: @x:2 + IDENT [32] { + name: @ac:0:0 } } } @@ -1830,52 +1583,38 @@ CALL [1] { } } loop_step: { - CALL [38] { - function: _||_ - args: { - IDENT [39] { - name: @x:2 - } - CALL [40] { - function: _>_ - args: { - IDENT [41] { - name: @c:2 - } - CONSTANT [42] { value: 1 } - } - } - } + IDENT [33] { + name: @index1 } } result: { - IDENT [43] { - name: @x:2 + IDENT [34] { + name: @ac:0:0 } } } - COMPREHENSION [44] { - iter_var: @c:3 + COMPREHENSION [35] { + iter_var: @it:0:0 iter_range: { - LIST [45] { + LIST [36] { elements: { - CONSTANT [46] { value: 2 } + CONSTANT [37] { value: 2 } } } } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - CONSTANT [47] { value: false } + CONSTANT [38] { value: false } } loop_condition: { - CALL [48] { + CALL [39] { function: @not_strictly_false args: { - CALL [49] { + CALL [40] { function: !_ args: { - IDENT [50] { - name: @x:3 + IDENT [41] { + name: @ac:0:0 } } } @@ -1883,27 +1622,13 @@ CALL [1] { } } loop_step: { - CALL [51] { - function: _||_ - args: { - IDENT [52] { - name: @x:3 - } - CALL [53] { - function: _>_ - args: { - IDENT [54] { - name: @c:3 - } - CONSTANT [55] { value: 1 } - } - } - } + IDENT [42] { + name: @index1 } } result: { - IDENT [56] { - name: @x:3 + IDENT [43] { + name: @ac:0:0 } } } @@ -1941,13 +1666,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [12] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [13] { name: @index0 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [14] { elements: { @@ -1962,18 +1687,18 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:1 + name: @ac:0:0 } LIST [18] { elements: { COMPREHENSION [19] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [20] { name: @index0 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [21] { elements: { @@ -1988,7 +1713,7 @@ CALL [1] { function: _+_ args: { IDENT [24] { - name: @x:0 + name: @ac:1:0 } LIST [25] { elements: { @@ -1996,7 +1721,7 @@ CALL [1] { function: _+_ args: { IDENT [27] { - name: @c:0 + name: @it:1:0 } CONSTANT [28] { value: 1 } } @@ -2008,7 +1733,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:0 + name: @ac:1:0 } } } @@ -2019,7 +1744,7 @@ CALL [1] { } result: { IDENT [30] { - name: @x:1 + name: @ac:0:0 } } } @@ -2047,7 +1772,7 @@ CALL [31] { function: _==_ args: { COMPREHENSION [30] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { LIST [1] { elements: { @@ -2056,7 +1781,7 @@ CALL [31] { } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [24] { elements: { @@ -2071,12 +1796,12 @@ CALL [31] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { COMPREHENSION [23] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [6] { elements: { @@ -2086,7 +1811,7 @@ CALL [31] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [15] { elements: { @@ -2104,10 +1829,10 @@ CALL [31] { function: _==_ args: { IDENT [12] { - name: @c:0 + name: @it:1:0 } IDENT [14] { - name: @c:1 + name: @it:0:0 } } } @@ -2115,26 +1840,26 @@ CALL [31] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { IDENT [11] { - name: @c:0 + name: @it:1:0 } } } } } IDENT [20] { - name: @x:0 + name: @ac:1:0 } } } } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } @@ -2145,7 +1870,7 @@ CALL [31] { } result: { IDENT [29] { - name: @x:1 + name: @ac:0:0 } } } @@ -2173,160 +1898,73 @@ CALL [1] { args: { LIST [2] { elements: { - LIST [3] { - elements: { - CONSTANT [4] { value: 1 } - CONSTANT [5] { value: 2 } - CONSTANT [6] { value: 3 } - } - } - } - } - CALL [7] { - function: _==_ - args: { - COMPREHENSION [8] { - iter_var: @c:1 + COMPREHENSION [3] { + iter_var: @it:0:0 iter_range: { - IDENT [9] { - name: @index0 - } - } - accu_var: @x:1 - accu_init: { - LIST [10] { + LIST [4] { elements: { + CONSTANT [5] { value: 1 } + CONSTANT [6] { value: 2 } + CONSTANT [7] { value: 3 } } } } - loop_condition: { - CONSTANT [11] { value: true } - } - loop_step: { - CALL [12] { - function: _+_ - args: { - IDENT [13] { - name: @x:1 - } - LIST [14] { - elements: { - COMPREHENSION [15] { - iter_var: @c:0 - iter_range: { - IDENT [16] { - name: @index0 - } - } - accu_var: @x:0 - accu_init: { - LIST [17] { - elements: { - } - } - } - loop_condition: { - CONSTANT [18] { value: true } - } - loop_step: { - CALL [19] { - function: _+_ - args: { - IDENT [20] { - name: @x:0 - } - LIST [21] { - elements: { - CALL [22] { - function: _+_ - args: { - IDENT [23] { - name: @c:0 - } - CONSTANT [24] { value: 1 } - } - } - } - } - } - } - } - result: { - IDENT [25] { - name: @x:0 - } - } - } - } - } - } - } - } - result: { - IDENT [26] { - name: @x:1 - } - } - } - COMPREHENSION [27] { - iter_var: @c:3 - iter_range: { - IDENT [28] { - name: @index0 - } - } - accu_var: @x:3 + accu_var: @ac:0:0 accu_init: { - LIST [29] { + LIST [8] { elements: { } } } loop_condition: { - CONSTANT [30] { value: true } + CONSTANT [9] { value: true } } loop_step: { - CALL [31] { + CALL [10] { function: _+_ args: { - IDENT [32] { - name: @x:3 + IDENT [11] { + name: @ac:0:0 } - LIST [33] { + LIST [12] { elements: { - COMPREHENSION [34] { - iter_var: @c:2 + COMPREHENSION [13] { + iter_var: @it:1:0 iter_range: { - IDENT [35] { - name: @index0 + LIST [14] { + elements: { + CONSTANT [15] { value: 1 } + CONSTANT [16] { value: 2 } + CONSTANT [17] { value: 3 } + } } } - accu_var: @x:2 + accu_var: @ac:1:0 accu_init: { - LIST [36] { + LIST [18] { elements: { } } } loop_condition: { - CONSTANT [37] { value: true } + CONSTANT [19] { value: true } } loop_step: { - CALL [38] { + CALL [20] { function: _+_ args: { - IDENT [39] { - name: @x:2 + IDENT [21] { + name: @ac:1:0 } - LIST [40] { + LIST [22] { elements: { - CALL [41] { + CALL [23] { function: _+_ args: { - IDENT [42] { - name: @c:2 + IDENT [24] { + name: @it:1:0 } - CONSTANT [43] { value: 1 } + CONSTANT [25] { value: 1 } } } } @@ -2335,8 +1973,8 @@ CALL [1] { } } result: { - IDENT [44] { - name: @x:2 + IDENT [26] { + name: @ac:1:0 } } } @@ -2346,13 +1984,24 @@ CALL [1] { } } result: { - IDENT [45] { - name: @x:3 + IDENT [27] { + name: @ac:0:0 } } } } } + CALL [28] { + function: _==_ + args: { + IDENT [29] { + name: @index0 + } + IDENT [30] { + name: @index0 + } + } + } } } Test case: INCLUSION_LIST @@ -2525,13 +2174,13 @@ CALL [1] { function: _==_ args: { COMPREHENSION [14] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { IDENT [15] { name: @index1 } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [16] { elements: { @@ -2546,18 +2195,18 @@ CALL [1] { function: _+_ args: { IDENT [19] { - name: @x:1 + name: @ac:0:0 } LIST [20] { elements: { COMPREHENSION [21] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { IDENT [22] { name: @index1 } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [23] { elements: { @@ -2572,7 +2221,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:0 + name: @ac:1:0 } LIST [27] { elements: { @@ -2589,7 +2238,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:0 + name: @ac:1:0 } } } @@ -2600,7 +2249,7 @@ CALL [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:0:0 } } } @@ -2647,7 +2296,7 @@ CALL [1] { function: _||_ args: { COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:0:0 iter_range: { LIST [10] { elements: { @@ -2672,7 +2321,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:0:0 accu_init: { CONSTANT [17] { value: false } } @@ -2684,7 +2333,7 @@ CALL [1] { function: !_ args: { IDENT [20] { - name: @x:0 + name: @ac:0:0 } } } @@ -2696,7 +2345,7 @@ CALL [1] { function: _||_ args: { IDENT [22] { - name: @x:0 + name: @ac:0:0 } CALL [23] { function: _>_ @@ -2705,7 +2354,7 @@ CALL [1] { function: _-_ args: { IDENT [25] { - name: @c:0 + name: @it:0:0 } CONSTANT [26] { value: 1 } } @@ -2718,7 +2367,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:0 + name: @ac:0:0 } } } @@ -2741,10 +2390,10 @@ CALL [1] { function: _+_ args: { IDENT [4] { - name: @c:0 + name: @it:1:0 } IDENT [5] { - name: @c:0 + name: @it:1:0 } } } @@ -2752,20 +2401,20 @@ CALL [1] { function: _+_ args: { IDENT [7] { - name: @c:1 + name: @it:0:0 } IDENT [8] { - name: @c:1 + name: @it:0:0 } } } } } COMPREHENSION [9] { - iter_var: @c:1 + iter_var: @it:0:0 iter_range: { COMPREHENSION [10] { - iter_var: @c:0 + iter_var: @it:1:0 iter_range: { LIST [11] { elements: { @@ -2774,7 +2423,7 @@ CALL [1] { } } } - accu_var: @x:0 + accu_var: @ac:1:0 accu_init: { LIST [14] { elements: { @@ -2789,7 +2438,7 @@ CALL [1] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:1:0 } LIST [18] { elements: { @@ -2810,12 +2459,12 @@ CALL [1] { } result: { IDENT [22] { - name: @x:0 + name: @ac:1:0 } } } } - accu_var: @x:1 + accu_var: @ac:0:0 accu_init: { LIST [23] { elements: { @@ -2830,7 +2479,7 @@ CALL [1] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:0:0 } LIST [27] { elements: { @@ -2851,7 +2500,7 @@ CALL [1] { } result: { IDENT [31] { - name: @x:1 + name: @ac:0:0 } } } diff --git a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline index 14ec4f9e6..bb02cd934 100644 --- a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline +++ b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline @@ -1607,13 +1607,13 @@ CALL [1] { LIST [18] { elements: { COMPREHENSION [19] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { IDENT [20] { name: @r0 } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { CONSTANT [21] { value: false } } @@ -1625,7 +1625,7 @@ CALL [1] { function: !_ args: { IDENT [24] { - name: @x:0 + name: @ac:0 } } } @@ -1637,13 +1637,13 @@ CALL [1] { function: _||_ args: { IDENT [26] { - name: @x:0 + name: @ac:0 } CALL [27] { function: _>_ args: { IDENT [28] { - name: @c:0 + name: @it:0 } CONSTANT [29] { value: 0 } } @@ -1653,7 +1653,7 @@ CALL [1] { } result: { IDENT [30] { - name: @x:0 + name: @ac:0 } } } @@ -1667,13 +1667,13 @@ CALL [1] { LIST [32] { elements: { COMPREHENSION [33] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { IDENT [34] { name: @r0 } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { CONSTANT [35] { value: false } } @@ -1685,7 +1685,7 @@ CALL [1] { function: !_ args: { IDENT [38] { - name: @x:1 + name: @ac:1 } } } @@ -1697,13 +1697,13 @@ CALL [1] { function: _||_ args: { IDENT [40] { - name: @x:1 + name: @ac:1 } CALL [41] { function: _>_ args: { IDENT [42] { - name: @c:1 + name: @it:1 } CONSTANT [43] { value: 0 } } @@ -1713,7 +1713,7 @@ CALL [1] { } result: { IDENT [44] { - name: @x:1 + name: @ac:1 } } } @@ -1731,13 +1731,13 @@ CALL [1] { LIST [46] { elements: { COMPREHENSION [47] { - iter_var: @c:2 + iter_var: @it:2 iter_range: { IDENT [48] { name: @r1 } } - accu_var: @x:2 + accu_var: @ac:2 accu_init: { CONSTANT [49] { value: false } } @@ -1749,7 +1749,7 @@ CALL [1] { function: !_ args: { IDENT [52] { - name: @x:2 + name: @ac:2 } } } @@ -1761,13 +1761,13 @@ CALL [1] { function: _||_ args: { IDENT [54] { - name: @x:2 + name: @ac:2 } CALL [55] { function: _>_ args: { IDENT [56] { - name: @c:2 + name: @it:2 } CONSTANT [57] { value: 1 } } @@ -1777,7 +1777,7 @@ CALL [1] { } result: { IDENT [58] { - name: @x:2 + name: @ac:2 } } } @@ -1793,13 +1793,13 @@ CALL [1] { LIST [60] { elements: { COMPREHENSION [61] { - iter_var: @c:3 + iter_var: @it:3 iter_range: { IDENT [62] { name: @r1 } } - accu_var: @x:3 + accu_var: @ac:3 accu_init: { CONSTANT [63] { value: false } } @@ -1811,7 +1811,7 @@ CALL [1] { function: !_ args: { IDENT [66] { - name: @x:3 + name: @ac:3 } } } @@ -1823,13 +1823,13 @@ CALL [1] { function: _||_ args: { IDENT [68] { - name: @x:3 + name: @ac:3 } CALL [69] { function: _>_ args: { IDENT [70] { - name: @c:3 + name: @it:3 } CONSTANT [71] { value: 1 } } @@ -1839,7 +1839,7 @@ CALL [1] { } result: { IDENT [72] { - name: @x:3 + name: @ac:3 } } } @@ -1922,13 +1922,13 @@ CALL [1] { LIST [17] { elements: { COMPREHENSION [18] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { IDENT [19] { name: @r0 } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { CONSTANT [20] { value: false } } @@ -1940,7 +1940,7 @@ CALL [1] { function: !_ args: { IDENT [23] { - name: @x:0 + name: @ac:0 } } } @@ -1952,13 +1952,13 @@ CALL [1] { function: _||_ args: { IDENT [25] { - name: @x:0 + name: @ac:0 } CALL [26] { function: _>_ args: { IDENT [27] { - name: @c:0 + name: @it:0 } CONSTANT [28] { value: 0 } } @@ -1968,7 +1968,7 @@ CALL [1] { } result: { IDENT [29] { - name: @x:0 + name: @ac:0 } } } @@ -1977,13 +1977,13 @@ CALL [1] { LIST [30] { elements: { COMPREHENSION [31] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { IDENT [32] { name: @r0 } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { CONSTANT [33] { value: false } } @@ -1995,7 +1995,7 @@ CALL [1] { function: !_ args: { IDENT [36] { - name: @x:1 + name: @ac:1 } } } @@ -2007,13 +2007,13 @@ CALL [1] { function: _||_ args: { IDENT [38] { - name: @x:1 + name: @ac:1 } CALL [39] { function: _>_ args: { IDENT [40] { - name: @c:1 + name: @it:1 } CONSTANT [41] { value: 0 } } @@ -2023,7 +2023,7 @@ CALL [1] { } result: { IDENT [42] { - name: @x:1 + name: @ac:1 } } } @@ -2036,13 +2036,13 @@ CALL [1] { LIST [43] { elements: { COMPREHENSION [44] { - iter_var: @c:2 + iter_var: @it:2 iter_range: { IDENT [45] { name: @r1 } } - accu_var: @x:2 + accu_var: @ac:2 accu_init: { CONSTANT [46] { value: false } } @@ -2054,7 +2054,7 @@ CALL [1] { function: !_ args: { IDENT [49] { - name: @x:2 + name: @ac:2 } } } @@ -2066,13 +2066,13 @@ CALL [1] { function: _||_ args: { IDENT [51] { - name: @x:2 + name: @ac:2 } CALL [52] { function: _==_ args: { IDENT [53] { - name: @c:2 + name: @it:2 } CONSTANT [54] { value: "a" } } @@ -2082,7 +2082,7 @@ CALL [1] { } result: { IDENT [55] { - name: @x:2 + name: @ac:2 } } } @@ -2093,13 +2093,13 @@ CALL [1] { LIST [56] { elements: { COMPREHENSION [57] { - iter_var: @c:3 + iter_var: @it:3 iter_range: { IDENT [58] { name: @r1 } } - accu_var: @x:3 + accu_var: @ac:3 accu_init: { CONSTANT [59] { value: false } } @@ -2111,7 +2111,7 @@ CALL [1] { function: !_ args: { IDENT [62] { - name: @x:3 + name: @ac:3 } } } @@ -2123,13 +2123,13 @@ CALL [1] { function: _||_ args: { IDENT [64] { - name: @x:3 + name: @ac:3 } CALL [65] { function: _==_ args: { IDENT [66] { - name: @c:3 + name: @it:3 } CONSTANT [67] { value: "a" } } @@ -2139,7 +2139,7 @@ CALL [1] { } result: { IDENT [68] { - name: @x:3 + name: @ac:3 } } } @@ -2194,13 +2194,13 @@ COMPREHENSION [1] { function: _&&_ args: { COMPREHENSION [9] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { IDENT [10] { name: @r0 } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { CONSTANT [11] { value: false } } @@ -2212,7 +2212,7 @@ COMPREHENSION [1] { function: !_ args: { IDENT [14] { - name: @x:0 + name: @ac:0 } } } @@ -2224,13 +2224,13 @@ COMPREHENSION [1] { function: _||_ args: { IDENT [16] { - name: @x:0 + name: @ac:0 } CALL [17] { function: _>_ args: { IDENT [18] { - name: @c:0 + name: @it:0 } CONSTANT [19] { value: 0 } } @@ -2240,18 +2240,18 @@ COMPREHENSION [1] { } result: { IDENT [20] { - name: @x:0 + name: @ac:0 } } } COMPREHENSION [21] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { IDENT [22] { name: @r0 } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { CONSTANT [23] { value: false } } @@ -2263,7 +2263,7 @@ COMPREHENSION [1] { function: !_ args: { IDENT [26] { - name: @x:1 + name: @ac:1 } } } @@ -2275,13 +2275,13 @@ COMPREHENSION [1] { function: _||_ args: { IDENT [28] { - name: @x:1 + name: @ac:1 } CALL [29] { function: _>_ args: { IDENT [30] { - name: @c:1 + name: @it:1 } CONSTANT [31] { value: 0 } } @@ -2291,7 +2291,7 @@ COMPREHENSION [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:1 } } } @@ -2301,13 +2301,13 @@ COMPREHENSION [1] { function: _&&_ args: { COMPREHENSION [34] { - iter_var: @c:2 + iter_var: @it:2 iter_range: { IDENT [35] { name: @r0 } } - accu_var: @x:2 + accu_var: @ac:2 accu_init: { CONSTANT [36] { value: false } } @@ -2319,7 +2319,7 @@ COMPREHENSION [1] { function: !_ args: { IDENT [39] { - name: @x:2 + name: @ac:2 } } } @@ -2331,13 +2331,13 @@ COMPREHENSION [1] { function: _||_ args: { IDENT [41] { - name: @x:2 + name: @ac:2 } CALL [42] { function: _>_ args: { IDENT [43] { - name: @c:2 + name: @it:2 } CONSTANT [44] { value: 1 } } @@ -2347,12 +2347,12 @@ COMPREHENSION [1] { } result: { IDENT [45] { - name: @x:2 + name: @ac:2 } } } COMPREHENSION [46] { - iter_var: @c:3 + iter_var: @it:3 iter_range: { LIST [47] { elements: { @@ -2360,7 +2360,7 @@ COMPREHENSION [1] { } } } - accu_var: @x:3 + accu_var: @ac:3 accu_init: { CONSTANT [49] { value: false } } @@ -2372,7 +2372,7 @@ COMPREHENSION [1] { function: !_ args: { IDENT [52] { - name: @x:3 + name: @ac:3 } } } @@ -2384,13 +2384,13 @@ COMPREHENSION [1] { function: _||_ args: { IDENT [54] { - name: @x:3 + name: @ac:3 } CALL [55] { function: _>_ args: { IDENT [56] { - name: @c:3 + name: @it:3 } CONSTANT [57] { value: 1 } } @@ -2400,7 +2400,7 @@ COMPREHENSION [1] { } result: { IDENT [58] { - name: @x:3 + name: @ac:3 } } } @@ -2444,13 +2444,13 @@ CALL [1] { } result: { COMPREHENSION [10] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { IDENT [11] { name: @r0 } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { LIST [12] { elements: { @@ -2465,18 +2465,18 @@ CALL [1] { function: _+_ args: { IDENT [15] { - name: @x:1 + name: @ac:1 } LIST [16] { elements: { COMPREHENSION [17] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { IDENT [18] { name: @r0 } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { LIST [19] { elements: { @@ -2491,7 +2491,7 @@ CALL [1] { function: _+_ args: { IDENT [22] { - name: @x:0 + name: @ac:0 } LIST [23] { elements: { @@ -2499,7 +2499,7 @@ CALL [1] { function: _+_ args: { IDENT [25] { - name: @c:0 + name: @it:0 } CONSTANT [26] { value: 1 } } @@ -2511,7 +2511,7 @@ CALL [1] { } result: { IDENT [27] { - name: @x:0 + name: @ac:0 } } } @@ -2522,7 +2522,7 @@ CALL [1] { } result: { IDENT [28] { - name: @x:1 + name: @ac:1 } } } @@ -2579,7 +2579,7 @@ CALL [31] { function: _==_ args: { COMPREHENSION [30] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { LIST [1] { elements: { @@ -2588,7 +2588,7 @@ CALL [31] { } } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { LIST [24] { elements: { @@ -2603,12 +2603,12 @@ CALL [31] { function: _+_ args: { IDENT [26] { - name: @x:1 + name: @ac:1 } LIST [27] { elements: { COMPREHENSION [23] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { LIST [6] { elements: { @@ -2618,7 +2618,7 @@ CALL [31] { } } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { LIST [15] { elements: { @@ -2636,10 +2636,10 @@ CALL [31] { function: _==_ args: { IDENT [12] { - name: @c:0 + name: @it:0 } IDENT [14] { - name: @c:1 + name: @it:1 } } } @@ -2647,26 +2647,26 @@ CALL [31] { function: _+_ args: { IDENT [17] { - name: @x:0 + name: @ac:0 } LIST [18] { elements: { IDENT [11] { - name: @c:0 + name: @it:0 } } } } } IDENT [20] { - name: @x:0 + name: @ac:0 } } } } result: { IDENT [22] { - name: @x:0 + name: @ac:0 } } } @@ -2677,7 +2677,7 @@ CALL [31] { } result: { IDENT [29] { - name: @x:1 + name: @ac:1 } } } @@ -2731,13 +2731,13 @@ COMPREHENSION [1] { function: _==_ args: { COMPREHENSION [10] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { IDENT [11] { name: @r0 } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { LIST [12] { elements: { @@ -2752,18 +2752,18 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [15] { - name: @x:1 + name: @ac:1 } LIST [16] { elements: { COMPREHENSION [17] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { IDENT [18] { name: @r0 } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { LIST [19] { elements: { @@ -2778,7 +2778,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [22] { - name: @x:0 + name: @ac:0 } LIST [23] { elements: { @@ -2786,7 +2786,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [25] { - name: @c:0 + name: @it:0 } CONSTANT [26] { value: 1 } } @@ -2798,7 +2798,7 @@ COMPREHENSION [1] { } result: { IDENT [27] { - name: @x:0 + name: @ac:0 } } } @@ -2809,18 +2809,18 @@ COMPREHENSION [1] { } result: { IDENT [28] { - name: @x:1 + name: @ac:1 } } } COMPREHENSION [29] { - iter_var: @c:3 + iter_var: @it:3 iter_range: { IDENT [30] { name: @r0 } } - accu_var: @x:3 + accu_var: @ac:3 accu_init: { LIST [31] { elements: { @@ -2835,18 +2835,18 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [34] { - name: @x:3 + name: @ac:3 } LIST [35] { elements: { COMPREHENSION [36] { - iter_var: @c:2 + iter_var: @it:2 iter_range: { IDENT [37] { name: @r0 } } - accu_var: @x:2 + accu_var: @ac:2 accu_init: { LIST [38] { elements: { @@ -2861,7 +2861,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [41] { - name: @x:2 + name: @ac:2 } LIST [42] { elements: { @@ -2869,7 +2869,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [44] { - name: @c:2 + name: @it:2 } CONSTANT [45] { value: 1 } } @@ -2881,7 +2881,7 @@ COMPREHENSION [1] { } result: { IDENT [46] { - name: @x:2 + name: @ac:2 } } } @@ -2892,7 +2892,7 @@ COMPREHENSION [1] { } result: { IDENT [47] { - name: @x:3 + name: @ac:3 } } } @@ -3137,13 +3137,13 @@ COMPREHENSION [1] { } result: { COMPREHENSION [16] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { IDENT [17] { name: @r0 } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { LIST [18] { elements: { @@ -3158,18 +3158,18 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [21] { - name: @x:1 + name: @ac:1 } LIST [22] { elements: { COMPREHENSION [23] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { IDENT [24] { name: @r0 } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { LIST [25] { elements: { @@ -3184,7 +3184,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [28] { - name: @x:0 + name: @ac:0 } LIST [29] { elements: { @@ -3198,7 +3198,7 @@ COMPREHENSION [1] { } result: { IDENT [31] { - name: @x:0 + name: @ac:0 } } } @@ -3209,7 +3209,7 @@ COMPREHENSION [1] { } result: { IDENT [32] { - name: @x:1 + name: @ac:1 } } } @@ -3326,7 +3326,7 @@ COMPREHENSION [1] { function: _||_ args: { COMPREHENSION [16] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { LIST [17] { elements: { @@ -3345,7 +3345,7 @@ COMPREHENSION [1] { } } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { CONSTANT [22] { value: false } } @@ -3357,7 +3357,7 @@ COMPREHENSION [1] { function: !_ args: { IDENT [25] { - name: @x:0 + name: @ac:0 } } } @@ -3369,7 +3369,7 @@ COMPREHENSION [1] { function: _||_ args: { IDENT [27] { - name: @x:0 + name: @ac:0 } CALL [28] { function: _>_ @@ -3378,7 +3378,7 @@ COMPREHENSION [1] { function: _-_ args: { IDENT [30] { - name: @c:0 + name: @it:0 } CONSTANT [31] { value: 1 } } @@ -3391,7 +3391,7 @@ COMPREHENSION [1] { } result: { IDENT [33] { - name: @x:0 + name: @ac:0 } } } @@ -3408,10 +3408,10 @@ Test case: MACRO_SHADOWED_VARIABLE_2 Source: ["foo", "bar"].map(x, [x + x, x + x]).map(x, [x + x, x + x]) =====> COMPREHENSION [1] { - iter_var: @c:1 + iter_var: @it:1 iter_range: { COMPREHENSION [2] { - iter_var: @c:0 + iter_var: @it:0 iter_range: { LIST [3] { elements: { @@ -3420,7 +3420,7 @@ COMPREHENSION [1] { } } } - accu_var: @x:0 + accu_var: @ac:0 accu_init: { LIST [6] { elements: { @@ -3435,7 +3435,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [9] { - name: @x:0 + name: @ac:0 } LIST [10] { elements: { @@ -3453,10 +3453,10 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [14] { - name: @c:0 + name: @it:0 } IDENT [15] { - name: @c:0 + name: @it:0 } } } @@ -3489,12 +3489,12 @@ COMPREHENSION [1] { } result: { IDENT [21] { - name: @x:0 + name: @ac:0 } } } } - accu_var: @x:1 + accu_var: @ac:1 accu_init: { LIST [22] { elements: { @@ -3509,7 +3509,7 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [25] { - name: @x:1 + name: @ac:1 } LIST [26] { elements: { @@ -3527,10 +3527,10 @@ COMPREHENSION [1] { function: _+_ args: { IDENT [30] { - name: @c:1 + name: @it:1 } IDENT [31] { - name: @c:1 + name: @it:1 } } } @@ -3563,7 +3563,7 @@ COMPREHENSION [1] { } result: { IDENT [37] { - name: @x:1 + name: @ac:1 } } } diff --git a/optimizer/src/test/resources/subexpression_unparsed.baseline b/optimizer/src/test/resources/subexpression_unparsed.baseline index 9675f3b3a..781f59990 100644 --- a/optimizer/src/test/resources/subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/subexpression_unparsed.baseline @@ -274,97 +274,97 @@ Test case: MULTIPLE_MACROS_1 Source: size([[1].exists(i, i > 0)]) + size([[1].exists(j, j > 0)]) + size([[2].exists(k, k > 1)]) + size([[2].exists(l, l > 1)]) == 4 =====> Result: true -[CASCADED_BINDS]: cel.bind(@r1, [2], cel.bind(@r0, [1], size([@r0.exists(@c:0, @c:0 > 0)]) + size([@r0.exists(@c:1, @c:1 > 0)])) + size([@r1.exists(@c:2, @c:2 > 1)]) + size([@r1.exists(@c:3, @c:3 > 1)])) == 4 -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1], [2]], size([@index0.exists(@c:0, @c:0 > 0)]) + size([@index0.exists(@c:1, @c:1 > 0)]) + size([@index1.exists(@c:2, @c:2 > 1)]) + size([@index1.exists(@c:3, @c:3 > 1)]) == 4) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], [2], @c:0 > 0, @x:0 || @index2, @c:1 > 0, @x:1 || @index4, @c:2 > 1, @x:2 || @index6, @c:3 > 1, @x:3 || @index8], size([@index0.exists(@c:0, @index2)]) + size([@index0.exists(@c:1, @index4)]) + size([@index1.exists(@c:2, @index6)]) + size([@index1.exists(@c:3, @index8)]) == 4) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1], [2], @x:0 || @c:0 > 0, @x:1 || @c:1 > 0, @x:2 || @c:2 > 1, @x:3 || @c:3 > 1], size([@index0.exists(@c:0, @c:0 > 0)]) + size([@index0.exists(@c:1, @c:1 > 0)]) + size([@index1.exists(@c:2, @c:2 > 1)]) + size([@index1.exists(@c:3, @c:3 > 1)]) == 4) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1], [2], @index0.exists(@c:0, @c:0 > 0), @index0.exists(@c:1, @c:1 > 0), size([@index2]) + size([@index3]), @index1.exists(@c:2, @c:2 > 1), @index4 + size([@index5]), @index1.exists(@c:3, @c:3 > 1), @index6 + size([@index7])], @index8 == 4) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1], [2], [@index0.exists(@c:0, @c:0 > 0)], [@index0.exists(@c:1, @c:1 > 0)], [@index1.exists(@c:2, @c:2 > 1)], [@index1.exists(@c:3, @c:3 > 1)], size(@index2) + size(@index3) + size(@index4) + size(@index5)], @index6 == 4) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1], [2], size([@index0.exists(@c:0, @c:0 > 0)]), size([@index0.exists(@c:1, @c:1 > 0)]), size([@index1.exists(@c:2, @c:2 > 1)]), size([@index1.exists(@c:3, @c:3 > 1)])], @index2 + @index3 + @index4 + @index5 == 4) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1], [2], size([@index0.exists(@c:0, @c:0 > 0)]) + size([@index0.exists(@c:1, @c:1 > 0)]), @index2 + size([@index1.exists(@c:2, @c:2 > 1)]), @index3 + size([@index1.exists(@c:3, @c:3 > 1)])], @index4 == 4) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1], [2], size([@index0.exists(@c:0, @c:0 > 0)]) + size([@index0.exists(@c:1, @c:1 > 0)]) + size([@index1.exists(@c:2, @c:2 > 1)])], @index2 + size([@index1.exists(@c:3, @c:3 > 1)]) == 4) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1], [2], size([@index0.exists(@c:0, @c:0 > 0)]) + size([@index0.exists(@c:1, @c:1 > 0)]) + size([@index1.exists(@c:2, @c:2 > 1)]) + size([@index1.exists(@c:3, @c:3 > 1)])], @index2 == 4) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1], [2]], size([@index0.exists(@c:0, @c:0 > 0)]) + size([@index0.exists(@c:1, @c:1 > 0)]) + size([@index1.exists(@c:2, @c:2 > 1)]) + size([@index1.exists(@c:3, @c:3 > 1)]) == 4) +[CASCADED_BINDS]: cel.bind(@r1, [2], cel.bind(@r0, [1], size([@r0.exists(@it:0, @it:0 > 0)]) + size([@r0.exists(@it:1, @it:1 > 0)])) + size([@r1.exists(@it:2, @it:2 > 1)]) + size([@r1.exists(@it:3, @it:3 > 1)])) == 4 +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @it:0:0 > 0, @ac:0:0 || @index1, [2], @it:0:0 > 1, @ac:0:0 || @index4], size([@index0.exists(@it:0:0, @index1)]) + size([@index0.exists(@it:0:0, @index1)]) + size([@index3.exists(@it:0:0, @index4)]) + size([@index3.exists(@it:0:0, @index4)]) == 4) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:0:0 || @it:0:0 > 0, @ac:0:0 || @it:0:0 > 1, [1], [2]], size([@index2.exists(@it:0:0, @it:0:0 > 0)]) + size([@index2.exists(@it:0:0, @it:0:0 > 0)]) + size([@index3.exists(@it:0:0, @it:0:0 > 1)]) + size([@index3.exists(@it:0:0, @it:0:0 > 1)]) == 4) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), [2].exists(@it:0:0, @it:0:0 > 1), size([@index0]), size([@index1]), @index2 + @index2 + @index3 + @index3], @index4 == 4) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [[2].exists(@it:0:0, @it:0:0 > 1)], size(@index0), size(@index1)], @index2 + @index2 + @index3 + @index3 == 4) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) Test case: MULTIPLE_MACROS_2 Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] =====> Result: true -[CASCADED_BINDS]: cel.bind(@r1, ["a"], cel.bind(@r0, [1], [@r0.exists(@c:0, @c:0 > 0)] + [@r0.exists(@c:1, @c:1 > 0)]) + [@r1.exists(@c:2, @c:2 == "a")] + [@r1.exists(@c:3, @c:3 == "a")]) == [true, true, true, true] -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1], ["a"]], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)] + [@index1.exists(@c:2, @c:2 == "a")] + [@index1.exists(@c:3, @c:3 == "a")] == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], ["a"], @c:0 > 0, @x:0 || @index2, @c:1 > 0, @x:1 || @index4, @c:2 == "a", @x:2 || @index6, @c:3 == "a", @x:3 || @index8, [true, true, true, true]], [@index0.exists(@c:0, @index2)] + [@index0.exists(@c:1, @index4)] + [@index1.exists(@c:2, @index6)] + [@index1.exists(@c:3, @index8)] == @index10) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1], ["a"], @x:0 || @c:0 > 0, @x:1 || @c:1 > 0, @x:2 || @c:2 == "a", @x:3 || @c:3 == "a", [true, true, true, true]], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)] + [@index1.exists(@c:2, @c:2 == "a")] + [@index1.exists(@c:3, @c:3 == "a")] == @index6) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1], ["a"], @index0.exists(@c:0, @c:0 > 0), @index0.exists(@c:1, @c:1 > 0), @index1.exists(@c:2, @c:2 == "a"), [@index2] + [@index3] + [@index4], @index1.exists(@c:3, @c:3 == "a")], @index5 + [@index6] == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1], ["a"], [@index0.exists(@c:0, @c:0 > 0)], [@index0.exists(@c:1, @c:1 > 0)], [@index1.exists(@c:2, @c:2 == "a")], [@index1.exists(@c:3, @c:3 == "a")]], @index2 + @index3 + @index4 + @index5 == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1], ["a"], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)], @index2 + [@index1.exists(@c:2, @c:2 == "a")], @index3 + [@index1.exists(@c:3, @c:3 == "a")]], @index4 == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1], ["a"], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)] + [@index1.exists(@c:2, @c:2 == "a")]], @index2 + [@index1.exists(@c:3, @c:3 == "a")] == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1], ["a"], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)] + [@index1.exists(@c:2, @c:2 == "a")] + [@index1.exists(@c:3, @c:3 == "a")]], @index2 == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1], ["a"]], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)] + [@index1.exists(@c:2, @c:2 == "a")] + [@index1.exists(@c:3, @c:3 == "a")] == [true, true, true, true]) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1], ["a"]], [@index0.exists(@c:0, @c:0 > 0)] + [@index0.exists(@c:1, @c:1 > 0)] + [@index1.exists(@c:2, @c:2 == "a")] + [@index1.exists(@c:3, @c:3 == "a")] == [true, true, true, true]) +[CASCADED_BINDS]: cel.bind(@r1, ["a"], cel.bind(@r0, [1], [@r0.exists(@it:0, @it:0 > 0)] + [@r0.exists(@it:1, @it:1 > 0)]) + [@r1.exists(@it:2, @it:2 == "a")] + [@r1.exists(@it:3, @it:3 == "a")]) == [true, true, true, true] +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @it:0:0 > 0, @ac:0:0 || @index1, ["a"], @it:0:1 == "a", @ac:0:1 || @index4, [true, true, true, true]], [@index0.exists(@it:0:0, @index1)] + [@index0.exists(@it:0:0, @index1)] + [@index3.exists(@it:0:1, @index4)] + [@index3.exists(@it:0:1, @index4)] == @index6) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:0:0 || @it:0:0 > 0, @ac:0:1 || @it:0:1 == "a", [1], ["a"], [true, true, true, true]], [@index2.exists(@it:0:0, @it:0:0 > 0)] + [@index2.exists(@it:0:0, @it:0:0 > 0)] + [@index3.exists(@it:0:1, @it:0:1 == "a")] + [@index3.exists(@it:0:1, @it:0:1 == "a")] == @index4) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), ["a"].exists(@it:0:1, @it:0:1 == "a"), [@index0], [@index1], @index2 + @index2 + @index3 + @index3], @index4 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) Test case: MULTIPLE_MACROS_3 Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) =====> Result: false -[CASCADED_BINDS]: cel.bind(@r0, [1], @r0.exists(@c:0, @c:0 > 0) && @r0.exists(@c:1, @c:1 > 0) && @r0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @c:0 > 0, @x:0 || @index1, @c:1 > 0, @x:1 || @index3, @c:2 > 1, @x:2 || @index5, [2], @c:3 > 1, @x:3 || @index8], @index0.exists(@c:0, @index1) && @index0.exists(@c:1, @index3) && @index0.exists(@c:2, @index5) && @index7.exists(@c:3, @index8)) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1], @x:0 || @c:0 > 0, @x:1 || @c:1 > 0, @x:2 || @c:2 > 1, @x:3 || @c:3 > 1, [2]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && @index5.exists(@c:3, @c:3 > 1)) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1], @index0.exists(@c:0, @c:0 > 0), @index0.exists(@c:1, @c:1 > 0), @index0.exists(@c:2, @c:2 > 1), [2].exists(@c:3, @c:3 > 1)], @index1 && @index2 && @index3 && @index4) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0), @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)], @index1 && @index2) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1]], @index0.exists(@c:0, @c:0 > 0) && @index0.exists(@c:1, @c:1 > 0) && @index0.exists(@c:2, @c:2 > 1) && [2].exists(@c:3, @c:3 > 1)) +[CASCADED_BINDS]: cel.bind(@r0, [1], @r0.exists(@it:0, @it:0 > 0) && @r0.exists(@it:1, @it:1 > 0) && @r0.exists(@it:2, @it:2 > 1) && [2].exists(@it:3, @it:3 > 1)) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @it:0:0 > 0, @ac:0:0 || @index1, @it:0:0 > 1, @ac:0:0 || @index3, [2]], @index0.exists(@it:0:0, @index1) && @index0.exists(@it:0:0, @index1) && @index0.exists(@it:0:0, @index3) && @index5.exists(@it:0:0, @index3)) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:0:0 || @it:0:0 > 0, @ac:0:0 || @it:0:0 > 1, [1], [2]], @index2.exists(@it:0:0, @it:0:0 > 0) && @index2.exists(@it:0:0, @it:0:0 > 0) && @index2.exists(@it:0:0, @it:0:0 > 1) && @index3.exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1, [1].exists(@it:0:0, @it:0:0 > 1), [2].exists(@it:0:0, @it:0:0 > 1)], @index0 && @index0 && @index2 && @index3) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1, [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)], @index0 && @index0 && @index2) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) Test case: NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [[2, 3, 4], [2, 3, 4], [2, 3, 4]] =====> Result: true -[CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@c:1, @r0.map(@c:0, @c:0 + 1))) == cel.bind(@r1, [2, 3, 4], [@r1, @r1, @r1]) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], [2, 3, 4], @c:0 + 1, [@index2], @x:0 + @index3, [@index1, @index1, @index1]], @index0.map(@c:1, @index0.map(@c:0, @index2)) == @index5) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3], [2, 3, 4], [@c:0 + 1], @index0.map(@c:0, @c:0 + 1), @x:1 + [@index3], @index0.map(@c:1, @index3)], @index5 == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3], [2, 3, 4], @x:0 + [@c:0 + 1], [@index0.map(@c:0, @c:0 + 1)]], @index0.map(@c:1) == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3], [2, 3, 4], @index0.map(@c:0, @c:0 + 1)], @index0.map(@c:1, @index2) == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1, 2, 3], [2, 3, 4], [@index0.map(@c:0, @c:0 + 1)]], @index0.map(@c:1) == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1, 2, 3], [2, 3, 4], @x:1 + [@index0.map(@c:0, @c:0 + 1)]], @index0.map(@c:1) == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2, 3], [2, 3, 4], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1))], @index2 == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == [@index1, @index1, @index1]) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == [@index1, @index1, @index1]) +[CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@it:1, @r0.map(@it:0, @it:0 + 1))) == cel.bind(@r1, [2, 3, 4], [@r1, @r1, @r1]) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1)) == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], [2, 3, 4], @it:1:0 + 1, [@index2], @ac:1:0 + @index3, [@index1, @index1, @index1]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index2)) == @index5) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3], [2, 3, 4], [@it:1:0 + 1], @index0.map(@it:1:0, @it:1:0 + 1), @ac:0:0 + [@index3], @index0.map(@it:0:0, @index3)], @index5 == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3], [2, 3, 4], @ac:1:0 + [@it:1:0 + 1], [@index0.map(@it:1:0, @it:1:0 + 1)]], @index0.map(@it:0:0) == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3], [2, 3, 4], @index0.map(@it:1:0, @it:1:0 + 1)], @index0.map(@it:0:0, @index2) == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1, 2, 3], [2, 3, 4], [@index0.map(@it:1:0, @it:1:0 + 1)]], @index0.map(@it:0:0) == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1, 2, 3], [2, 3, 4], @ac:0:0 + [@index0.map(@it:1:0, @it:1:0 + 1)]], @index0.map(@it:0:0) == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2, 3], [2, 3, 4], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1))], @index2 == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1)) == [@index1, @index1, @index1]) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1)) == [@index1, @index1, @index1]) Test case: NESTED_MACROS_2 Source: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] =====> Result: true -[CASCADED_BINDS]: [1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1)) == [[1], [2]] -[BLOCK_COMMON_SUBEXPR_ONLY]: [1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1)) == [[1], [2]] -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], [1, 2, 3], @c:0 == @c:1, [@c:0], @x:0 + @index3, @index2 ? @index4 : @x:0, [1], [2], [@index6, @index7]], @index0.map(@c:1, @index1.filter(@c:0, @index2)) == @index8) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([@x:0 + [@c:0], (@c:0 == @c:1) ? @index0 : @x:0, [1, 2, 3].filter(@c:0, @c:0 == @c:1), @x:1 + [@index2], [1, 2].map(@c:1, @index2), [[1], [2]]], @index4 == @index5) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([(@c:0 == @c:1) ? (@x:0 + [@c:0]) : @x:0, [[1, 2, 3].filter(@c:0, @c:0 == @c:1)]], [1, 2].map(@c:1) == [[1], [2]]) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3].filter(@c:0, @c:0 == @c:1)], [1, 2].map(@c:1, @index0) == [[1], [2]]) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[[1, 2, 3].filter(@c:0, @c:0 == @c:1)]], [1, 2].map(@c:1) == [[1], [2]]) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([@x:1 + [[1, 2, 3].filter(@c:0, @c:0 == @c:1)]], [1, 2].map(@c:1) == [[1], [2]]) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1))], @index0 == [[1], [2]]) -[BLOCK_RECURSION_DEPTH_8]: [1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1)) == [[1], [2]] -[BLOCK_RECURSION_DEPTH_9]: [1, 2].map(@c:1, [1, 2, 3].filter(@c:0, @c:0 == @c:1)) == [[1], [2]] +[CASCADED_BINDS]: [1, 2].map(@it:1, [1, 2, 3].filter(@it:0, @it:0 == @it:1)) == [[1], [2]] +[BLOCK_COMMON_SUBEXPR_ONLY]: [1, 2].map(@it:0:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)) == [[1], [2]] +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], [1, 2, 3], @it:1:0 == @it:0:0, [@it:1:0], @ac:1:0 + @index3, @index2 ? @index4 : @ac:1:0, [1], [2], [@index6, @index7]], @index0.map(@it:0:0, @index1.filter(@it:1:0, @index2)) == @index8) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:1:0 + [@it:1:0], (@it:1:0 == @it:0:0) ? @index0 : @ac:1:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0), @ac:0:0 + [@index2], [1, 2].map(@it:0:0, @index2), [[1], [2]]], @index4 == @index5) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([(@it:1:0 == @it:0:0) ? (@ac:1:0 + [@it:1:0]) : @ac:1:0, [[1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)]], [1, 2].map(@it:0:0) == [[1], [2]]) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)], [1, 2].map(@it:0:0, @index0) == [[1], [2]]) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[[1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)]], [1, 2].map(@it:0:0) == [[1], [2]]) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([@ac:0:0 + [[1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)]], [1, 2].map(@it:0:0) == [[1], [2]]) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2].map(@it:0:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0))], @index0 == [[1], [2]]) +[BLOCK_RECURSION_DEPTH_8]: [1, 2].map(@it:0:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)) == [[1], [2]] +[BLOCK_RECURSION_DEPTH_9]: [1, 2].map(@it:0:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)) == [[1], [2]] Test case: ADJACENT_NESTED_MACROS Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) =====> Result: true -[CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@c:1, @r0.map(@c:0, @c:0 + 1)) == @r0.map(@c:3, @r0.map(@c:2, @c:2 + 1))) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], @c:0 + 1, [@index1], @x:0 + @index2, @c:2 + 1, [@index4], @x:2 + @index5], @index0.map(@c:1, @index0.map(@c:0, @index1)) == @index0.map(@c:3, @index0.map(@c:2, @index4))) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3], [@c:0 + 1], @index0.map(@c:0, @c:0 + 1), @x:1 + [@index2], @index0.map(@c:1, @index2), [@c:2 + 1], @index0.map(@c:2, @c:2 + 1), @x:3 + [@index6], @index0.map(@c:3, @index6)], @index4 == @index8) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3], @x:0 + [@c:0 + 1], [@index0.map(@c:0, @c:0 + 1)], @x:2 + [@c:2 + 1], [@index0.map(@c:2, @c:2 + 1)]], @index0.map(@c:1) == @index0.map(@c:3)) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3], @index0.map(@c:0, @c:0 + 1), @index0.map(@c:2, @c:2 + 1)], @index0.map(@c:1, @index1) == @index0.map(@c:3, @index2)) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[1, 2, 3], [@index0.map(@c:0, @c:0 + 1)], [@index0.map(@c:2, @c:2 + 1)]], @index0.map(@c:1) == @index0.map(@c:3)) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([[1, 2, 3], @x:1 + [@index0.map(@c:0, @c:0 + 1)], @x:3 + [@index0.map(@c:2, @c:2 + 1)]], @index0.map(@c:1) == @index0.map(@c:3)) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2, 3], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)), @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))], @index1 == @index2) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1, 2, 3]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1, 2, 3]], @index0.map(@c:1, @index0.map(@c:0, @c:0 + 1)) == @index0.map(@c:3, @index0.map(@c:2, @c:2 + 1))) +[CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@it:1, @r0.map(@it:0, @it:0 + 1)) == @r0.map(@it:3, @r0.map(@it:2, @it:2 + 1))) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1))], @index1 == @index1) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], @it:1:0 + 1, [@index1], @ac:1:0 + @index2], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == @index0.map(@it:0:0, @index0.map(@it:1:0, @index1))) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([[@it:1:0 + 1], [1, 2, 3].map(@it:1:0, @it:1:0 + 1), @ac:0:0 + [@index1], [1, 2, 3].map(@it:0:0, @index1)], @index3 == @index3) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([@ac:1:0 + [@it:1:0 + 1], [[1, 2, 3].map(@it:1:0, @it:1:0 + 1)], [1, 2, 3].map(@it:0:0)], @index2 == @index2) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[1, 2, 3].map(@it:1:0, @it:1:0 + 1), [1, 2, 3].map(@it:0:0, @index0)], @index1 == @index1) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[[1, 2, 3].map(@it:1:0, @it:1:0 + 1)], [1, 2, 3].map(@it:0:0)], @index1 == @index1) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([@ac:0:0 + [[1, 2, 3].map(@it:1:0, @it:1:0 + 1)], [1, 2, 3].map(@it:0:0)], @index1 == @index1) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[1, 2, 3].map(@it:0:0, [1, 2, 3].map(@it:1:0, @it:1:0 + 1))], @index0 == @index0) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([[1, 2, 3].map(@it:0:0, [1, 2, 3].map(@it:1:0, @it:1:0 + 1))], @index0 == @index0) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([[1, 2, 3].map(@it:0:0, [1, 2, 3].map(@it:1:0, @it:1:0 + 1))], @index0 == @index0) Test case: INCLUSION_LIST Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] @@ -402,49 +402,49 @@ Test case: MACRO_ITER_VAR_NOT_REFERENCED Source: [1,2].map(i, [1, 2].map(i, [3,4])) == [[[3, 4], [3, 4]], [[3, 4], [3, 4]]] =====> Result: true -[CASCADED_BINDS]: cel.bind(@r1, [3, 4], cel.bind(@r0, [1, 2], @r0.map(@c:1, @r0.map(@c:0, @r1))) == cel.bind(@r2, [@r1, @r1], [@r2, @r2])) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2], [3, 4], [@index1, @index1]], @index0.map(@c:1, @index0.map(@c:0, @index1)) == [@index2, @index2]) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], [3, 4], [@index1, @index1], [@index1], @x:0 + @index3, [@index2, @index2]], @index0.map(@c:1, @index0.map(@c:0, @index1)) == @index5) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([[[3, 4], [3, 4]], [1, 2], [[3, 4]], @index1.map(@c:0, [3, 4]), @x:1 + [@index3], @index1.map(@c:1, @index3)], @index5 == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([[[3, 4], [3, 4]], [1, 2], @x:0 + [[3, 4]], [@index1.map(@c:0, [3, 4])]], @index1.map(@c:1) == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([[[3, 4], [3, 4]], [1, 2], @index1.map(@c:0, [3, 4])], @index1.map(@c:1, @index2) == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([[[3, 4], [3, 4]], [1, 2], [@index1.map(@c:0, [3, 4])]], @index1.map(@c:1) == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([[[3, 4], [3, 4]], [1, 2], @x:1 + [@index1.map(@c:0, [3, 4])]], @index1.map(@c:1) == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([[[3, 4], [3, 4]], [1, 2], @index1.map(@c:1, @index1.map(@c:0, [3, 4]))], @index2 == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([[[3, 4], [3, 4]], [1, 2]], @index1.map(@c:1, @index1.map(@c:0, [3, 4])) == [@index0, @index0]) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([[[3, 4], [3, 4]], [1, 2]], @index1.map(@c:1, @index1.map(@c:0, [3, 4])) == [@index0, @index0]) +[CASCADED_BINDS]: cel.bind(@r1, [3, 4], cel.bind(@r0, [1, 2], @r0.map(@it:1, @r0.map(@it:0, @r1))) == cel.bind(@r2, [@r1, @r1], [@r2, @r2])) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2], [3, 4], [@index1, @index1]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == [@index2, @index2]) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], [3, 4], [@index1, @index1], [@index1], @ac:1:0 + @index3, [@index2, @index2]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == @index5) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([[[3, 4], [3, 4]], [1, 2], [[3, 4]], @index1.map(@it:1:0, [3, 4]), @ac:0:0 + [@index3], @index1.map(@it:0:0, @index3)], @index5 == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([[[3, 4], [3, 4]], [1, 2], @ac:1:0 + [[3, 4]], [@index1.map(@it:1:0, [3, 4])]], @index1.map(@it:0:0) == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([[[3, 4], [3, 4]], [1, 2], @index1.map(@it:1:0, [3, 4])], @index1.map(@it:0:0, @index2) == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([[[3, 4], [3, 4]], [1, 2], [@index1.map(@it:1:0, [3, 4])]], @index1.map(@it:0:0) == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([[[3, 4], [3, 4]], [1, 2], @ac:0:0 + [@index1.map(@it:1:0, [3, 4])]], @index1.map(@it:0:0) == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([[[3, 4], [3, 4]], [1, 2], @index1.map(@it:0:0, @index1.map(@it:1:0, [3, 4]))], @index2 == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([[[3, 4], [3, 4]], [1, 2]], @index1.map(@it:0:0, @index1.map(@it:1:0, [3, 4])) == [@index0, @index0]) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([[[3, 4], [3, 4]], [1, 2]], @index1.map(@it:0:0, @index1.map(@it:1:0, [3, 4])) == [@index0, @index0]) Test case: MACRO_SHADOWED_VARIABLE Source: [x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3 =====> Result: true -[CASCADED_BINDS]: cel.bind(@r0, x - 1, cel.bind(@r1, @r0 > 3, [@r1 ? @r0 : 5].exists(@c:0, @c:0 - 1 > 3) || @r1)) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@c:0, @c:0 - 1 > 3) || @index1) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([x - 1, @index0 > 3, @index1 ? @index0 : 5, [@index2], @c:0 - 1, @index4 > 3, @x:0 || @index5], @index3.exists(@c:0, @index5) || @index1) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([x - 1 > 3, @index0 ? (x - 1) : 5, @c:0 - 1 > 3, [@index1], @x:0 || @index2], @index3.exists(@c:0, @index2) || @index0) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5], @x:0 || @c:0 - 1 > 3, @index1.exists(@c:0, @c:0 - 1 > 3)], @index3 || @index0) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3)], @index1 || @index0) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@c:0, @c:0 - 1 > 3) || @index0) +[CASCADED_BINDS]: cel.bind(@r0, x - 1, cel.bind(@r1, @r0 > 3, [@r1 ? @r0 : 5].exists(@it:0, @it:0 - 1 > 3) || @r1)) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index1) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([x - 1, @index0 > 3, @index1 ? @index0 : 5, [@index2], @it:0:0 - 1, @index4 > 3, @ac:0:0 || @index5], @index3.exists(@it:0:0, @index5) || @index1) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([x - 1 > 3, @index0 ? (x - 1) : 5, @it:0:0 - 1 > 3, [@index1], @ac:0:0 || @index2], @index3.exists(@it:0:0, @index2) || @index0) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5], @ac:0:0 || @it:0:0 - 1 > 3, @index1.exists(@it:0:0, @it:0:0 - 1 > 3)], @index3 || @index0) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3)], @index1 || @index0) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([x - 1 > 3], [@index0 ? (x - 1) : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index0) Test case: MACRO_SHADOWED_VARIABLE_2 Source: ["foo", "bar"].map(x, [x + x, x + x]).map(x, [x + x, x + x]) =====> Result: [[[foofoo, foofoo, foofoo, foofoo], [foofoo, foofoo, foofoo, foofoo]], [[barbar, barbar, barbar, barbar], [barbar, barbar, barbar, barbar]]] -[CASCADED_BINDS]: ["foo", "bar"].map(@c:0, cel.bind(@r0, @c:0 + @c:0, [@r0, @r0])).map(@c:1, cel.bind(@r1, @c:1 + @c:1, [@r1, @r1])) -[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([@c:0 + @c:0, @c:1 + @c:1], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_1]: cel.@block([@c:0 + @c:0, @c:1 + @c:1, ["foo", "bar"], [@index0, @index0], [@index3], @x:0 + @index4, [@index1, @index1], [@index6], @x:1 + @index7], @index2.map(@c:0, @index3).map(@c:1, @index6)) -[BLOCK_RECURSION_DEPTH_2]: cel.@block([@c:0 + @c:0, @c:1 + @c:1, [[@index0, @index0]], ["foo", "bar"].map(@c:0, [@index0, @index0]), [[@index1, @index1]]], @index3.map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_3]: cel.@block([@c:0 + @c:0, @c:1 + @c:1, @x:0 + [[@index0, @index0]], @x:1 + [[@index1, @index1]]], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_4]: cel.@block([@c:0 + @c:0, @c:1 + @c:1, ["foo", "bar"].map(@c:0, [@index0, @index0])], @index2.map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_5]: cel.@block([@c:0 + @c:0, @c:1 + @c:1], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_6]: cel.@block([@c:0 + @c:0, @c:1 + @c:1], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_7]: cel.@block([@c:0 + @c:0, @c:1 + @c:1], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_8]: cel.@block([@c:0 + @c:0, @c:1 + @c:1], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) -[BLOCK_RECURSION_DEPTH_9]: cel.@block([@c:0 + @c:0, @c:1 + @c:1], ["foo", "bar"].map(@c:0, [@index0, @index0]).map(@c:1, [@index1, @index1])) +[CASCADED_BINDS]: ["foo", "bar"].map(@it:0, cel.bind(@r0, @it:0 + @it:0, [@r0, @r0])).map(@it:1, cel.bind(@r1, @it:1 + @it:1, [@r1, @r1])) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, ["foo", "bar"], [@index0, @index0], [@index3], @ac:1:0 + @index4, [@index1, @index1], [@index6], @ac:0:0 + @index7], @index2.map(@it:1:0, @index3).map(@it:0:0, @index6)) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, [[@index0, @index0]], ["foo", "bar"].map(@it:1:0, [@index0, @index0]), [[@index1, @index1]]], @index3.map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, @ac:1:0 + [[@index0, @index0]], @ac:0:0 + [[@index1, @index1]]], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, ["foo", "bar"].map(@it:1:0, [@index0, @index0])], @index2.map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) Test case: PRESENCE_TEST Source: has({'a': true}.a) && {'a':true}['a'] From 78dfcb527526de25e1b5f498bdde6f140c302801 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 21 Aug 2024 11:31:43 -0700 Subject: [PATCH 24/33] Enable UnsignedLongs by default in CelOptions PiperOrigin-RevId: 665962755 --- common/src/main/java/dev/cel/common/CelOptions.java | 1 + common/src/main/java/dev/cel/common/ExprFeatures.java | 3 ++- .../java/dev/cel/common/internal/ProtoAdapterTest.java | 2 +- .../cel/common/values/ProtoMessageValueProviderTest.java | 8 ++++---- .../java/dev/cel/extensions/CelMathExtensionsTest.java | 2 ++ testing/src/test/java/dev/cel/testing/EvalSyncTest.java | 5 +++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/dev/cel/common/CelOptions.java b/common/src/main/java/dev/cel/common/CelOptions.java index c5288aa2f..2568099fb 100644 --- a/common/src/main/java/dev/cel/common/CelOptions.java +++ b/common/src/main/java/dev/cel/common/CelOptions.java @@ -211,6 +211,7 @@ public static Builder current() { return newBuilder() .enableReservedIds(true) .enableUnsignedComparisonAndArithmeticIsUnsigned(true) + .enableUnsignedLongs(true) .enableRegexPartialMatch(true) .errorOnDuplicateMapKeys(true) .errorOnIntWrap(true) diff --git a/common/src/main/java/dev/cel/common/ExprFeatures.java b/common/src/main/java/dev/cel/common/ExprFeatures.java index 2bc36b6e6..c4170bbb9 100644 --- a/common/src/main/java/dev/cel/common/ExprFeatures.java +++ b/common/src/main/java/dev/cel/common/ExprFeatures.java @@ -159,7 +159,8 @@ public enum ExprFeatures { UNSIGNED_COMPARISON_AND_ARITHMETIC_IS_UNSIGNED, ENABLE_NAMESPACED_DECLARATIONS, ERROR_ON_WRAP, - ERROR_ON_DUPLICATE_KEYS); + ERROR_ON_DUPLICATE_KEYS, + ENABLE_UNSIGNED_LONGS); public static final ImmutableSet LEGACY = ImmutableSet.of(LEGACY_JAVA_EQUALITY); } diff --git a/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java b/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java index 151f79f49..8126ec949 100644 --- a/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java +++ b/common/src/test/java/dev/cel/common/internal/ProtoAdapterTest.java @@ -106,7 +106,7 @@ public static List data() { }, {1L, Int64Value.of(1L), LEGACY}, {1L, Any.pack(Int64Value.of(1L)), LEGACY}, - {1L, UInt64Value.of(1L), LEGACY}, + {UnsignedLong.valueOf(1L), UInt64Value.of(1L), LEGACY}, {"hello", StringValue.of("hello"), LEGACY}, {"hello", Any.pack(StringValue.of("hello")), LEGACY}, {"hello", Value.newBuilder().setStringValue("hello").build(), LEGACY}, diff --git a/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java b/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java index de08149f0..6dfb01344 100644 --- a/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java +++ b/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java @@ -106,9 +106,9 @@ public void newValue_createProtoMessage_fieldsPopulated() { assertThat(protoMessageValue.select(StringValue.create("single_int64"))) .isEqualTo(IntValue.create(2L)); assertThat(protoMessageValue.select(StringValue.create("single_uint32"))) - .isEqualTo(UintValue.create(3L, false)); + .isEqualTo(UintValue.create(3L, true)); assertThat(protoMessageValue.select(StringValue.create("single_uint64"))) - .isEqualTo(UintValue.create(4L, false)); + .isEqualTo(UintValue.create(4L, true)); assertThat(protoMessageValue.select(StringValue.create("single_double"))) .isEqualTo(DoubleValue.create(5.5d)); assertThat(protoMessageValue.select(StringValue.create("single_bool"))) @@ -178,9 +178,9 @@ public void newValue_createProtoMessage_wrappersPopulated() { assertThat(protoMessageValue.select(StringValue.create("single_int64_wrapper")).value()) .isEqualTo(2L); assertThat(protoMessageValue.select(StringValue.create("single_uint32_wrapper")).value()) - .isEqualTo(3L); + .isEqualTo(UnsignedLong.valueOf(3L)); assertThat(protoMessageValue.select(StringValue.create("single_uint64_wrapper")).value()) - .isEqualTo(4L); + .isEqualTo(UnsignedLong.valueOf(4L)); assertThat(protoMessageValue.select(StringValue.create("single_double_wrapper")).value()) .isEqualTo(5.5d); assertThat(protoMessageValue.select(StringValue.create("single_bool_wrapper")).value()) diff --git a/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java index 320e7dfea..a0bf39e77 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java @@ -44,10 +44,12 @@ public class CelMathExtensionsTest { CelOptions.current().enableUnsignedLongs(false).build(); private static final CelCompiler CEL_COMPILER = CelCompilerFactory.standardCelCompilerBuilder() + .setOptions(CEL_OPTIONS) .addLibraries(CelExtensions.math(CEL_OPTIONS)) .build(); private static final CelRuntime CEL_RUNTIME = CelRuntimeFactory.standardCelRuntimeBuilder() + .setOptions(CEL_OPTIONS) .addLibraries(CelExtensions.math(CEL_OPTIONS)) .build(); diff --git a/testing/src/test/java/dev/cel/testing/EvalSyncTest.java b/testing/src/test/java/dev/cel/testing/EvalSyncTest.java index e516d9780..438ba0c43 100644 --- a/testing/src/test/java/dev/cel/testing/EvalSyncTest.java +++ b/testing/src/test/java/dev/cel/testing/EvalSyncTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; +import com.google.common.primitives.UnsignedLong; import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.ByteString; @@ -80,8 +81,8 @@ public static List data() { {StringValue.of("test"), "test"}, {Int32Value.of(1), 1L}, {Int64Value.of(1), 1L}, - {UInt32Value.of(1), 1L}, - {UInt64Value.of(1), 1L}, + {UInt32Value.of(1), UnsignedLong.valueOf(1L)}, + {UInt64Value.of(1), UnsignedLong.valueOf(1L)}, {BytesValue.of(ByteString.copyFromUtf8("test")), ByteString.copyFromUtf8("test")}, }); } From 2e97ede352ebeee5c3a41616b47e05a036ad10c4 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 21 Aug 2024 11:40:33 -0700 Subject: [PATCH 25/33] Add an option to prevent breaking apart a comprehension in CSE PiperOrigin-RevId: 665966630 --- .../optimizers/SubexpressionOptimizer.java | 68 +- .../SubexpressionOptimizerBaselineTest.java | 3 + .../SubexpressionOptimizerTest.java | 20 + ...old_before_subexpression_unparsed.baseline | 44 + ..._comprehension_structure_retained.baseline | 3422 +++++++++++++++++ .../resources/subexpression_unparsed.baseline | 44 + 6 files changed, 3600 insertions(+), 1 deletion(-) create mode 100644 optimizer/src/test/resources/subexpression_ast_block_common_subexpr_comprehension_structure_retained.baseline diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java index e6c327915..293481d8f 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java @@ -551,7 +551,51 @@ private boolean canEliminate( && !(navigableExpr.getKind().equals(Kind.LIST) && navigableExpr.expr().list().elements().isEmpty()) && containsEliminableFunctionOnly(navigableExpr) - && !ineligibleExprs.contains(navigableExpr.expr()); + && !ineligibleExprs.contains(navigableExpr.expr()) + && containsComprehensionIdentInSubexpr(navigableExpr); + } + + private boolean containsComprehensionIdentInSubexpr(CelNavigableMutableExpr navExpr) { + if (!cseOptions.retainComprehensionStructure()) { + return true; + } + + if (navExpr.getKind().equals(Kind.COMPREHENSION)) { + return true; + } + + ImmutableList comprehensionIdents = + navExpr + .allNodes() + .filter( + node -> + node.getKind().equals(Kind.IDENT) + && (node.expr() + .ident() + .name() + .startsWith(MANGLED_COMPREHENSION_ITER_VAR_PREFIX) + || node.expr() + .ident() + .name() + .startsWith(MANGLED_COMPREHENSION_ACCU_VAR_PREFIX))) + .collect(toImmutableList()); + + if (comprehensionIdents.isEmpty()) { + return true; + } + + for (CelNavigableMutableExpr ident : comprehensionIdents) { + CelNavigableMutableExpr parent = ident.parent().orElse(null); + while (parent != null) { + if (parent.getKind().equals(Kind.COMPREHENSION)) { + return false; + } + + parent = parent.parent().orElse(null); + } + } + + return true; } /** @@ -628,6 +672,8 @@ public abstract static class SubexpressionOptimizerOptions { public abstract boolean enableCelBlock(); + public abstract boolean retainComprehensionStructure(); + public abstract int subexpressionMaxRecursionDepth(); public abstract ImmutableSet eliminableFunctions(); @@ -684,6 +730,25 @@ public abstract static class Builder { */ public abstract Builder subexpressionMaxRecursionDepth(int value); + /** + * If configured true, SubexpressionOptimizer will not break apart a subexpression containing + * a comprehension's iter_var and accu_var without the surrounding comprehension. + * + *

An example expression {@code ['foo'].map(x, [x+x]) + ['foo'].map(x, [x+x, x+x])} is + * optimized as (note the common subexpr x+x that leverage the iteration variable): + * + *

+       *   Disabled: {@code cel.@block([["foo"], @it0 + @it0], @index0.map(@it0, [@index1])
+       *       + @index0.map(@it0, [@index1, @index1]))}
+       *   Enabled: {@code cel.@block([["foo"]], @index0.map(@it0, [@it0 + @it0])
+       *       + @index0.map(@it0, [@it0 + @it0, @it0 + @it0]))}
+       *  
+ * + * If targeting CEL-Java for the runtime, the recommended setting is to + * leave this disabled for maximal optimization efficiency. + */ + public abstract Builder retainComprehensionStructure(boolean value); + abstract ImmutableSet.Builder eliminableFunctionsBuilder(); /** @@ -718,6 +783,7 @@ public static Builder newBuilder() { .iterationLimit(500) .populateMacroCalls(false) .enableCelBlock(false) + .retainComprehensionStructure(false) .subexpressionMaxRecursionDepth(0); } diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index 2cb3df813..e2035be1b 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -71,6 +71,7 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase { private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS = SubexpressionOptimizerOptions.newBuilder() + .retainComprehensionStructure(false) .populateMacroCalls(true) .enableCelBlock(true) .addEliminableFunctions("pure_custom_func") @@ -352,6 +353,8 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio private enum CseTestOptimizer { CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()), BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS), + BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED( + OPTIMIZER_COMMON_OPTIONS.toBuilder().retainComprehensionStructure(true).build()), BLOCK_RECURSION_DEPTH_1( OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()), BLOCK_RECURSION_DEPTH_2( diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java index f4cec706d..3febca67c 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java @@ -201,6 +201,26 @@ public void cse_withCelBlock_noop(@TestParameter CseNoOpTestCase testCase) throw assertThat(CEL_UNPARSER.unparse(optimizedAst)).isEqualTo(testCase.source); } + @Test + public void cse_withComprehensionStructureRetained() throws Exception { + CelAbstractSyntaxTree ast = + CEL.compile("['foo'].map(x, [x+x]) + ['foo'].map(x, [x+x, x+x])").getAst(); + CelOptimizer celOptimizer = + newCseOptimizer( + SubexpressionOptimizerOptions.newBuilder() + .populateMacroCalls(true) + .enableCelBlock(true) + .retainComprehensionStructure(true) + .build()); + + CelAbstractSyntaxTree optimizedAst = celOptimizer.optimize(ast); + + assertThat(CEL_UNPARSER.unparse(optimizedAst)) + .isEqualTo( + "cel.@block([[\"foo\"]], @index0.map(@it:0:0, [@it:0:0 + @it:0:0]) +" + + " @index0.map(@it:0:0, [@it:0:0 + @it:0:0, @it:0:0 + @it:0:0]))"); + } + @Test public void cse_applyConstFoldingAfter() throws Exception { CelAbstractSyntaxTree ast = diff --git a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline index 7324d1716..54207adf1 100644 --- a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline @@ -4,6 +4,7 @@ Source: size([1,2]) + size([1,2]) + 1 == 5 Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -20,6 +21,7 @@ Source: 2 + size([1,2]) + size([1,2]) + 1 == 7 Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -36,6 +38,7 @@ Source: size([0]) + size([0]) + size([1,2]) + size([1,2]) == 6 Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -52,6 +55,7 @@ Source: 5 + size([0]) + size([0]) + size([1,2]) + size([1,2]) + size([1,2,3]) + Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -68,6 +72,7 @@ Source: timestamp(int(timestamp(1000000000))).getFullYear() + timestamp(int(time Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -84,6 +89,7 @@ Source: {"a": 2}["a"] + {"a": 2}["a"] * {"a": 2}["a"] == 6 Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -100,6 +106,7 @@ Source: {'a': {'b': 1}, 'c': {'b': 1}, 'd': {'e': {'b': 1}}, 'e': {'e': {'b': 1} Result: {a={b=1}, c={b=1}, d={e={b=1}}, e={e={b=1}}} [CASCADED_BINDS]: cel.bind(@r0, {"b": 1}, cel.bind(@r1, {"e": @r0}, {"a": @r0, "c": @r0, "d": @r1, "e": @r1})) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{"b": 1}, {"e": @index0}], {"a": @index0, "c": @index0, "d": @index1, "e": @index1}) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{"b": 1}, {"e": @index0}], {"a": @index0, "c": @index0, "d": @index1, "e": @index1}) [BLOCK_RECURSION_DEPTH_1]: cel.@block([{"b": 1}, {"e": @index0}], {"a": @index0, "c": @index0, "d": @index1, "e": @index1}) [BLOCK_RECURSION_DEPTH_2]: cel.@block([{"e": {"b": 1}}, {"b": 1}], {"a": @index1, "c": @index1, "d": @index0, "e": @index0}) [BLOCK_RECURSION_DEPTH_3]: cel.@block([{"e": {"b": 1}}, {"b": 1}], {"a": @index1, "c": @index1, "d": @index0, "e": @index0}) @@ -116,6 +123,7 @@ Source: [1, [1,2,3,4], 2, [1,2,3,4], 5, [1,2,3,4], 7, [[1,2], [1,2,3,4]], [1,2]] Result: [1, [1, 2, 3, 4], 2, [1, 2, 3, 4], 5, [1, 2, 3, 4], 7, [[1, 2], [1, 2, 3, 4]], [1, 2]] [CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3, 4], cel.bind(@r1, [1, 2], [1, @r0, 2, @r0, 5, @r0, 7, [@r1, @r0], @r1])) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3, 4], [1, 2], [@index1, @index0]], [1, @index0, 2, @index0, 5, @index0, 7, @index2, @index1]) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) @@ -132,6 +140,7 @@ Source: msg.single_int64 + msg.single_int64 == 6 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, @r0 + @r0) == 6 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64], @index0 + @index0 == 6) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64], @index0 + @index0 == 6) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, @index0 + @index0], @index1 == 6) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64], @index0 + @index0 == 6) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64], @index0 + @index0 == 6) @@ -148,6 +157,7 @@ Source: msg.oneof_type.payload.single_int64 + msg.oneof_type.payload.single_int3 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, @r1 + @r0.single_int32 + @r1) + msg.single_int64 + @r0.oneof_type.payload.single_int64) == 31 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], @index1 + @index0.single_int32 + @index1 + msg.single_int64 + @index0.oneof_type.payload.single_int64 == 31) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, @index0.single_int64], @index1 + @index0.single_int32 + @index1 + msg.single_int64 + @index0.oneof_type.payload.single_int64 == 31) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, @index1.single_int32, @index2 + @index3, @index4 + @index2, msg.single_int64, @index5 + @index6, @index1.oneof_type, @index8.payload, @index9.single_int64, @index7 + @index10], @index11 == 31) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64, @index1 + @index0.single_int32, @index2 + @index1 + msg.single_int64, @index0.oneof_type.payload, @index3 + @index4.single_int64], @index5 == 31) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, msg.oneof_type.payload, @index0 + @index1.single_int32 + @index0, @index1.oneof_type.payload.single_int64, @index2 + msg.single_int64 + @index3], @index4 == 31) @@ -164,6 +174,7 @@ Source: true || msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.one Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -180,6 +191,7 @@ Source: msg.oneof_type.payload.map_int32_int64[1] + msg.oneof_type.payload.map_i Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload.map_int32_int64[1], @r0 + @r0 + @r0) == 15 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload.map_int32_int64[1]], @index0 + @index0 + @index0 == 15) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload.map_int32_int64[1]], @index0 + @index0 + @index0 == 15) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_int32_int64, @index2[1], @index3 + @index3, @index4 + @index3], @index5 == 15) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.map_int32_int64[1], @index1 + @index1 + @index1], @index2 == 15) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.map_int32_int64, @index0[1]], @index1 + @index1 + @index1 == 15) @@ -196,6 +208,7 @@ Source: msg.oneof_type.payload.map_int32_int64[0] + msg.oneof_type.payload.map_i Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload.map_int32_int64, @r0[0] + @r0[1] + @r0[2]) == 8 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload.map_int32_int64], @index0[0] + @index0[1] + @index0[2] == 8) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload.map_int32_int64], @index0[0] + @index0[1] + @index0[2] == 8) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_int32_int64, @index2[0], @index2[1], @index3 + @index4, @index2[2], @index5 + @index6], @index7 == 8) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.map_int32_int64, @index1[0] + @index1[1], @index2 + @index1[2]], @index3 == 8) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.map_int32_int64, @index0[0] + @index0[1] + @index0[2]], @index1 == 8) @@ -212,6 +225,7 @@ Source: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type. Result: 0 [CASCADED_BINDS]: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 [BLOCK_COMMON_SUBEXPR_ONLY]: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.oneof_type, @index2.payload, @index3.oneof_type, @index4.payload, @index5.oneof_type, @index6.payload], @index7.single_int64) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.oneof_type.payload, @index1.oneof_type.payload, @index2.oneof_type.payload], @index3.single_int64) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.oneof_type, @index0.payload.oneof_type.payload], @index1.oneof_type.payload.single_int64) @@ -228,6 +242,7 @@ Source: (msg.single_int64 > 0 ? msg.single_int64 : 0) == 3 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, (@r0 > 0) ? @r0 : 0) == 3 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64], ((@index0 > 0) ? @index0 : 0) == 3) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64], ((@index0 > 0) ? @index0 : 0) == 3) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, @index0 > 0, @index1 ? @index0 : 0], @index2 == 3) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64, (@index0 > 0) ? @index0 : 0], @index1 == 3) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64], ((@index0 > 0) ? @index0 : 0) == 3) @@ -244,6 +259,7 @@ Source: false ? false : (msg.single_int64) + ((msg.single_int64 + 1) * 2) == 11 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, @r0 + (@r0 + 1) * 2) == 11 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64], @index0 + (@index0 + 1) * 2 == 11) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64], @index0 + (@index0 + 1) * 2 == 11) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, @index0 + 1, @index1 * 2, @index0 + @index2], @index3 == 11) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64, (@index0 + 1) * 2], @index0 + @index1 == 11) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64, @index0 + (@index0 + 1) * 2], @index1 == 11) @@ -260,6 +276,7 @@ Source: (msg.single_int64 > 0 ? (msg.single_int32 > 0 ? msg.single_int64 + msg.s Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, (@r0 > 0) ? cel.bind(@r1, msg.single_int32, (@r1 > 0) ? (@r0 + @r1) : 0) : 0) == 8 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64, msg.single_int32], ((@index0 > 0) ? ((@index1 > 0) ? (@index0 + @index1) : 0) : 0) == 8) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64, msg.single_int32], ((@index0 > 0) ? ((@index1 > 0) ? (@index0 + @index1) : 0) : 0) == 8) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, msg.single_int32, @index0 > 0, @index1 > 0, @index0 + @index1, @index3 ? @index4 : 0, @index2 ? @index5 : 0], @index6 == 8) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64, msg.single_int32, (@index1 > 0) ? (@index0 + @index1) : 0, (@index0 > 0) ? @index2 : 0], @index3 == 8) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64, msg.single_int32, (@index0 > 0) ? ((@index1 > 0) ? (@index0 + @index1) : 0) : 0], @index2 == 8) @@ -276,6 +293,7 @@ Source: size([[1].exists(i, i > 0)]) + size([[1].exists(j, j > 0)]) + size([[2]. Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -292,6 +310,7 @@ Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -308,6 +327,7 @@ Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && Result: false [CASCADED_BINDS]: false [BLOCK_COMMON_SUBEXPR_ONLY]: false +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: false [BLOCK_RECURSION_DEPTH_1]: false [BLOCK_RECURSION_DEPTH_2]: false [BLOCK_RECURSION_DEPTH_3]: false @@ -324,6 +344,7 @@ Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [[2, 3, 4], [2, 3, 4], [2, 3, Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -340,6 +361,7 @@ Source: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -356,6 +378,7 @@ Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map( Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -372,6 +395,7 @@ Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -388,6 +412,7 @@ Source: 2 in {'a': 1, 2: {true: false}, 3: {true: false}} Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -404,6 +429,7 @@ Source: [1,2].map(i, [1, 2].map(i, [3,4])) == [[[3, 4], [3, 4]], [[3, 4], [3, 4] Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -420,6 +446,7 @@ Source: [x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3 Result: true [CASCADED_BINDS]: cel.bind(@r0, x - 1, cel.bind(@r1, @r0 > 3, [@r1 ? @r0 : 5].exists(@it:0, @it:0 - 1 > 3) || @r1)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index1) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index1) [BLOCK_RECURSION_DEPTH_1]: cel.@block([x - 1, @index0 > 3, @index1 ? @index0 : 5, [@index2], @it:0:0 - 1, @index4 > 3, @ac:0:0 || @index5], @index3.exists(@it:0:0, @index5) || @index1) [BLOCK_RECURSION_DEPTH_2]: cel.@block([x - 1 > 3, @index0 ? (x - 1) : 5, @it:0:0 - 1 > 3, [@index1], @ac:0:0 || @index2], @index3.exists(@it:0:0, @index2) || @index0) [BLOCK_RECURSION_DEPTH_3]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5], @ac:0:0 || @it:0:0 - 1 > 3, @index1.exists(@it:0:0, @it:0:0 - 1 > 3)], @index3 || @index0) @@ -436,6 +463,7 @@ Source: ["foo", "bar"].map(x, [x + x, x + x]).map(x, [x + x, x + x]) Result: [[[foofoo, foofoo, foofoo, foofoo], [foofoo, foofoo, foofoo, foofoo]], [[barbar, barbar, barbar, barbar], [barbar, barbar, barbar, barbar]]] [CASCADED_BINDS]: [cel.bind(@r0, ["foofoo", "foofoo", "foofoo", "foofoo"], [@r0, @r0]), cel.bind(@r1, ["barbar", "barbar", "barbar", "barbar"], [@r1, @r1])] [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([["foofoo", "foofoo", "foofoo", "foofoo"], ["barbar", "barbar", "barbar", "barbar"]], [[@index0, @index0], [@index1, @index1]]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([["foofoo", "foofoo", "foofoo", "foofoo"], ["barbar", "barbar", "barbar", "barbar"]], [[@index0, @index0], [@index1, @index1]]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([["foofoo", "foofoo", "foofoo", "foofoo"], ["barbar", "barbar", "barbar", "barbar"], [@index0, @index0], [@index1, @index1]], [@index2, @index3]) [BLOCK_RECURSION_DEPTH_2]: cel.@block([["foofoo", "foofoo", "foofoo", "foofoo"], ["barbar", "barbar", "barbar", "barbar"]], [[@index0, @index0], [@index1, @index1]]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([["foofoo", "foofoo", "foofoo", "foofoo"], ["barbar", "barbar", "barbar", "barbar"]], [[@index0, @index0], [@index1, @index1]]) @@ -452,6 +480,7 @@ Source: has({'a': true}.a) && {'a':true}['a'] Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -468,6 +497,7 @@ Source: has({'a': true}.a) && has({'a': true}.a) Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -484,6 +514,7 @@ Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type, has(@r0.payload) ? @r0.payload.single_int64 : 0) == 10 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type], (has(@index0.payload) ? @index0.payload.single_int64 : 0) == 10) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type], (has(@index0.payload) ? @index0.payload.single_int64 : 0) == 10) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, has(@index0.payload), @index0.payload, @index2.single_int64, @index1 ? @index3 : 0], @index4 == 10) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type, @index0.payload.single_int64, has(@index0.payload) ? @index1 : 0], @index2 == 10) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type, has(@index0.payload) ? @index0.payload.single_int64 : 0], @index1 == 10) @@ -500,6 +531,7 @@ Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : msg Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type, cel.bind(@r1, @r0.payload.single_int64, has(@r0.payload) ? @r1 : (@r1 * 0))) == 10 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type, @index0.payload.single_int64], (has(@index0.payload) ? @index1 : (@index1 * 0)) == 10) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type, @index0.payload.single_int64], (has(@index0.payload) ? @index1 : (@index1 * 0)) == 10) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, has(@index0.payload), @index2 * 0, @index3 ? @index2 : @index4], @index5 == 10) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64, has(msg.oneof_type.payload), @index2 ? @index1 : (@index1 * 0)], @index3 == 10) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, has(msg.oneof_type.payload) ? @index0 : (@index0 * 0)], @index1 == 10) @@ -516,6 +548,7 @@ Source: (has(msg.oneof_type.payload.single_int64) ? msg.oneof_type.payload.singl Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, has(@r0.single_int64) ? @r1 : (@r1 * 0))) == 10 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], (has(@index0.single_int64) ? @index1 : (@index1 * 0)) == 10) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, @index0.single_int64], (has(@index0.single_int64) ? @index1 : (@index1 * 0)) == 10) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, has(@index1.single_int64), @index2 * 0, @index3 ? @index2 : @index4], @index5 == 10) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64, has(@index0.single_int64) ? @index1 : (@index1 * 0)], @index2 == 10) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, has(msg.oneof_type.payload.single_int64)], (@index1 ? @index0 : (@index0 * 0)) == 10) @@ -532,6 +565,7 @@ Source: (has(msg.oneof_type) && has(msg.oneof_type.payload) && has(msg.oneof_typ Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type, cel.bind(@r1, @r0.payload, (has(msg.oneof_type) && has(@r0.payload) && has(@r1.single_int64)) ? cel.bind(@r2, @r1.map_string_string, (has(@r1.map_string_string) && has(@r2.key)) ? (@r2.key == "A") : false) : false)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_string_string], (has(msg.oneof_type) && has(@index0.payload) && has(@index1.single_int64)) ? ((has(@index1.map_string_string) && has(@index2.key)) ? (@index2.key == "A") : false) : false) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_string_string], (has(msg.oneof_type) && has(@index0.payload) && has(@index1.single_int64)) ? ((has(@index1.map_string_string) && has(@index2.key)) ? (@index2.key == "A") : false) : false) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_string_string, has(msg.oneof_type), has(@index0.payload), @index3 && @index4, has(@index1.single_int64), @index5 && @index6, has(@index1.map_string_string), has(@index2.key), @index8 && @index9, @index2.key, @index11 == "A", @index10 ? @index12 : false], @index7 ? @index13 : false) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.map_string_string, has(msg.oneof_type.payload), has(msg.oneof_type) && @index2, @index3 && has(@index0.single_int64), has(@index0.map_string_string) && has(@index1.key), @index1.key == "A"], @index4 ? (@index5 ? @index6 : false) : false) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.map_string_string, msg.oneof_type.payload, has(msg.oneof_type) && has(msg.oneof_type.payload), (has(@index1.map_string_string) && has(@index0.key)) ? (@index0.key == "A") : false], (@index2 && has(@index1.single_int64)) ? @index3 : false) @@ -548,6 +582,7 @@ Source: [10, ?optional.none(), [?optional.none(), ?opt_x], [?optional.none(), ?o Result: true [CASCADED_BINDS]: cel.bind(@r0, [?opt_x], [10, @r0, @r0]) == cel.bind(@r1, [5], [10, @r1, @r1]) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[?opt_x], [5]], [10, @index0, @index0] == [10, @index1, @index1]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[?opt_x], [5]], [10, @index0, @index0] == [10, @index1, @index1]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[?opt_x], [5], [10, @index0, @index0], [10, @index1, @index1]], @index2 == @index3) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[?opt_x], [5]], [10, @index0, @index0] == [10, @index1, @index1]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[?opt_x], [5]], [10, @index0, @index0] == [10, @index1, @index1]) @@ -564,6 +599,7 @@ Source: {?'hello': optional.of('hello')}['hello'] + {?'hello': optional.of('hell Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -580,6 +616,7 @@ Source: {?'key': optional.of('test')}[?'bogus'].or({'key': 'test'}[?'bogus']).or Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -596,6 +633,7 @@ Source: TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: o Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -612,6 +650,7 @@ Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('h' + 'e' + 'l' + 'l' + Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -628,6 +667,7 @@ Source: 'hello world'.matches('h' + 'e' + 'l' + 'l' + 'o') Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -644,6 +684,7 @@ Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('hello') Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -660,6 +701,7 @@ Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('w' + 'o' + 'r' + 'l' + Result: true [CASCADED_BINDS]: true [BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true [BLOCK_RECURSION_DEPTH_1]: true [BLOCK_RECURSION_DEPTH_2]: true [BLOCK_RECURSION_DEPTH_3]: true @@ -676,6 +718,7 @@ Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_cus Result: 31 [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, non_pure_custom_func(@r1) + non_pure_custom_func(@r0.single_int32) + non_pure_custom_func(@r1))) + non_pure_custom_func(msg.single_int64) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64], non_pure_custom_func(@index2) + non_pure_custom_func(@index1.single_int32) + non_pure_custom_func(@index2) + non_pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64], non_pure_custom_func(@index0) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(@index0) + non_pure_custom_func(msg.single_int64)) @@ -692,6 +735,7 @@ Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func Result: 31 [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, pure_custom_func(@r0.single_int64), @r1 + pure_custom_func(@r0.single_int32) + @r1)) + pure_custom_func(msg.single_int64) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), @index1.single_int32, pure_custom_func(@index4), @index3 + @index5, @index6 + @index3, msg.single_int64, pure_custom_func(@index8)], @index7 + @index9) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64), pure_custom_func(@index0.single_int32), @index1 + @index2 + @index1, pure_custom_func(msg.single_int64)], @index3 + @index4) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, pure_custom_func(@index0), msg.oneof_type.payload.single_int32, @index1 + pure_custom_func(@index2) + @index1], @index3 + pure_custom_func(msg.single_int64)) diff --git a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_comprehension_structure_retained.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_comprehension_structure_retained.baseline new file mode 100644 index 000000000..61dc23350 --- /dev/null +++ b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_comprehension_structure_retained.baseline @@ -0,0 +1,3422 @@ +Test case: SIZE_1 +Source: size([1,2]) + size([1,2]) + 1 == 5 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: size + args: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + CONSTANT [6] { value: 2 } + } + } + } + } + } + } + CALL [7] { + function: _==_ + args: { + CALL [8] { + function: _+_ + args: { + CALL [9] { + function: _+_ + args: { + IDENT [10] { + name: @index0 + } + IDENT [11] { + name: @index0 + } + } + } + CONSTANT [12] { value: 1 } + } + } + CONSTANT [13] { value: 5 } + } + } + } +} +Test case: SIZE_2 +Source: 2 + size([1,2]) + size([1,2]) + 1 == 7 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: size + args: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + CONSTANT [6] { value: 2 } + } + } + } + } + } + } + CALL [7] { + function: _==_ + args: { + CALL [8] { + function: _+_ + args: { + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + CONSTANT [11] { value: 2 } + IDENT [12] { + name: @index0 + } + } + } + IDENT [13] { + name: @index0 + } + } + } + CONSTANT [14] { value: 1 } + } + } + CONSTANT [15] { value: 7 } + } + } + } +} +Test case: SIZE_3 +Source: size([0]) + size([0]) + size([1,2]) + size([1,2]) == 6 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: size + args: { + LIST [4] { + elements: { + CONSTANT [5] { value: 0 } + } + } + } + } + CALL [6] { + function: size + args: { + LIST [7] { + elements: { + CONSTANT [8] { value: 1 } + CONSTANT [9] { value: 2 } + } + } + } + } + } + } + CALL [10] { + function: _==_ + args: { + CALL [11] { + function: _+_ + args: { + CALL [12] { + function: _+_ + args: { + CALL [13] { + function: _+_ + args: { + IDENT [14] { + name: @index0 + } + IDENT [15] { + name: @index0 + } + } + } + IDENT [16] { + name: @index1 + } + } + } + IDENT [17] { + name: @index1 + } + } + } + CONSTANT [18] { value: 6 } + } + } + } +} +Test case: SIZE_4 +Source: 5 + size([0]) + size([0]) + size([1,2]) + size([1,2]) + size([1,2,3]) + size([1,2,3]) == 17 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: size + args: { + LIST [4] { + elements: { + CONSTANT [5] { value: 0 } + } + } + } + } + CALL [6] { + function: size + args: { + LIST [7] { + elements: { + CONSTANT [8] { value: 1 } + CONSTANT [9] { value: 2 } + } + } + } + } + CALL [10] { + function: size + args: { + LIST [11] { + elements: { + CONSTANT [12] { value: 1 } + CONSTANT [13] { value: 2 } + CONSTANT [14] { value: 3 } + } + } + } + } + } + } + CALL [15] { + function: _==_ + args: { + CALL [16] { + function: _+_ + args: { + CALL [17] { + function: _+_ + args: { + CALL [18] { + function: _+_ + args: { + CALL [19] { + function: _+_ + args: { + CALL [20] { + function: _+_ + args: { + CALL [21] { + function: _+_ + args: { + CONSTANT [22] { value: 5 } + IDENT [23] { + name: @index0 + } + } + } + IDENT [24] { + name: @index0 + } + } + } + IDENT [25] { + name: @index1 + } + } + } + IDENT [26] { + name: @index1 + } + } + } + IDENT [27] { + name: @index2 + } + } + } + IDENT [28] { + name: @index2 + } + } + } + CONSTANT [29] { value: 17 } + } + } + } +} +Test case: TIMESTAMP +Source: timestamp(int(timestamp(1000000000))).getFullYear() + timestamp(int(timestamp(75))).getFullYear() + timestamp(int(timestamp(50))).getFullYear() + timestamp(int(timestamp(1000000000))).getFullYear() + timestamp(int(timestamp(50))).getSeconds() + timestamp(int(timestamp(200))).getFullYear() + timestamp(int(timestamp(200))).getFullYear() + timestamp(int(timestamp(75))).getMinutes() + timestamp(int(timestamp(1000000000))).getFullYear() == 13934 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: getFullYear + target: { + CALL [4] { + function: timestamp + args: { + CALL [5] { + function: int + args: { + CALL [6] { + function: timestamp + args: { + CONSTANT [7] { value: 1000000000 } + } + } + } + } + } + } + } + args: { + } + } + CALL [8] { + function: timestamp + args: { + CALL [9] { + function: int + args: { + CALL [10] { + function: timestamp + args: { + CONSTANT [11] { value: 50 } + } + } + } + } + } + } + CALL [12] { + function: getFullYear + target: { + CALL [13] { + function: timestamp + args: { + CALL [14] { + function: int + args: { + CALL [15] { + function: timestamp + args: { + CONSTANT [16] { value: 200 } + } + } + } + } + } + } + } + args: { + } + } + CALL [17] { + function: timestamp + args: { + CALL [18] { + function: int + args: { + CALL [19] { + function: timestamp + args: { + CONSTANT [20] { value: 75 } + } + } + } + } + } + } + } + } + CALL [21] { + function: _==_ + args: { + CALL [22] { + function: _+_ + args: { + CALL [23] { + function: _+_ + args: { + CALL [24] { + function: _+_ + args: { + CALL [25] { + function: _+_ + args: { + CALL [26] { + function: _+_ + args: { + CALL [27] { + function: _+_ + args: { + CALL [28] { + function: _+_ + args: { + CALL [29] { + function: _+_ + args: { + IDENT [30] { + name: @index0 + } + CALL [31] { + function: getFullYear + target: { + IDENT [32] { + name: @index3 + } + } + args: { + } + } + } + } + CALL [33] { + function: getFullYear + target: { + IDENT [34] { + name: @index1 + } + } + args: { + } + } + } + } + IDENT [35] { + name: @index0 + } + } + } + CALL [36] { + function: getSeconds + target: { + IDENT [37] { + name: @index1 + } + } + args: { + } + } + } + } + IDENT [38] { + name: @index2 + } + } + } + IDENT [39] { + name: @index2 + } + } + } + CALL [40] { + function: getMinutes + target: { + IDENT [41] { + name: @index3 + } + } + args: { + } + } + } + } + IDENT [42] { + name: @index0 + } + } + } + CONSTANT [43] { value: 13934 } + } + } + } +} +Test case: MAP_INDEX +Source: {"a": 2}["a"] + {"a": 2}["a"] * {"a": 2}["a"] == 6 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _[_] + args: { + MAP [4] { + MAP_ENTRY [5] { + key: { + CONSTANT [6] { value: "a" } + } + value: { + CONSTANT [7] { value: 2 } + } + } + } + CONSTANT [8] { value: "a" } + } + } + } + } + CALL [9] { + function: _==_ + args: { + CALL [10] { + function: _+_ + args: { + IDENT [11] { + name: @index0 + } + CALL [12] { + function: _*_ + args: { + IDENT [13] { + name: @index0 + } + IDENT [14] { + name: @index0 + } + } + } + } + } + CONSTANT [15] { value: 6 } + } + } + } +} +Test case: NESTED_MAP_CONSTRUCTION +Source: {'a': {'b': 1}, 'c': {'b': 1}, 'd': {'e': {'b': 1}}, 'e': {'e': {'b': 1}}} +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "b" } + } + value: { + CONSTANT [6] { value: 1 } + } + } + } + MAP [7] { + MAP_ENTRY [8] { + key: { + CONSTANT [9] { value: "e" } + } + value: { + IDENT [10] { + name: @index0 + } + } + } + } + } + } + MAP [11] { + MAP_ENTRY [12] { + key: { + CONSTANT [13] { value: "a" } + } + value: { + IDENT [14] { + name: @index0 + } + } + } + MAP_ENTRY [15] { + key: { + CONSTANT [16] { value: "c" } + } + value: { + IDENT [17] { + name: @index0 + } + } + } + MAP_ENTRY [18] { + key: { + CONSTANT [19] { value: "d" } + } + value: { + IDENT [20] { + name: @index1 + } + } + } + MAP_ENTRY [21] { + key: { + CONSTANT [22] { value: "e" } + } + value: { + IDENT [23] { + name: @index1 + } + } + } + } + } +} +Test case: NESTED_LIST_CONSTRUCTION +Source: [1, [1,2,3,4], 2, [1,2,3,4], 5, [1,2,3,4], 7, [[1,2], [1,2,3,4]], [1,2]] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + CONSTANT [7] { value: 4 } + } + } + LIST [8] { + elements: { + CONSTANT [9] { value: 1 } + CONSTANT [10] { value: 2 } + } + } + } + } + LIST [11] { + elements: { + CONSTANT [12] { value: 1 } + IDENT [13] { + name: @index0 + } + CONSTANT [14] { value: 2 } + IDENT [15] { + name: @index0 + } + CONSTANT [16] { value: 5 } + IDENT [17] { + name: @index0 + } + CONSTANT [18] { value: 7 } + LIST [19] { + elements: { + IDENT [20] { + name: @index1 + } + IDENT [21] { + name: @index0 + } + } + } + IDENT [22] { + name: @index1 + } + } + } + } +} +Test case: SELECT +Source: msg.single_int64 + msg.single_int64 == 6 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.single_int64 + } + } + } + CALL [5] { + function: _==_ + args: { + CALL [6] { + function: _+_ + args: { + IDENT [7] { + name: @index0 + } + IDENT [8] { + name: @index0 + } + } + } + CONSTANT [9] { value: 6 } + } + } + } +} +Test case: SELECT_NESTED_1 +Source: msg.oneof_type.payload.single_int64 + msg.oneof_type.payload.single_int32 + msg.oneof_type.payload.single_int64 + msg.single_int64 + msg.oneof_type.payload.oneof_type.payload.single_int64 == 31 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + SELECT [6] { + IDENT [7] { + name: @index0 + }.single_int64 + } + } + } + CALL [8] { + function: _==_ + args: { + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + CALL [11] { + function: _+_ + args: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @index1 + } + SELECT [14] { + IDENT [15] { + name: @index0 + }.single_int32 + } + } + } + IDENT [16] { + name: @index1 + } + } + } + SELECT [17] { + IDENT [18] { + name: msg + }.single_int64 + } + } + } + SELECT [19] { + SELECT [20] { + SELECT [21] { + IDENT [22] { + name: @index0 + }.oneof_type + }.payload + }.single_int64 + } + } + } + CONSTANT [23] { value: 31 } + } + } + } +} +Test case: SELECT_NESTED_2 +Source: true || msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_bool || msg.oneof_type.payload.oneof_type.payload.oneof_type.child.child.payload.single_bool +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + SELECT [5] { + SELECT [6] { + SELECT [7] { + IDENT [8] { + name: msg + }.oneof_type + }.payload + }.oneof_type + }.payload + }.oneof_type + } + } + } + CALL [9] { + function: _||_ + args: { + CALL [10] { + function: _||_ + args: { + CONSTANT [11] { value: true } + SELECT [12] { + SELECT [13] { + SELECT [14] { + SELECT [15] { + IDENT [16] { + name: @index0 + }.payload + }.oneof_type + }.payload + }.single_bool + } + } + } + SELECT [17] { + SELECT [18] { + SELECT [19] { + SELECT [20] { + IDENT [21] { + name: @index0 + }.child + }.child + }.payload + }.single_bool + } + } + } + } +} +Test case: SELECT_NESTED_MESSAGE_MAP_INDEX_1 +Source: msg.oneof_type.payload.map_int32_int64[1] + msg.oneof_type.payload.map_int32_int64[1] + msg.oneof_type.payload.map_int32_int64[1] == 15 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _[_] + args: { + SELECT [4] { + SELECT [5] { + SELECT [6] { + IDENT [7] { + name: msg + }.oneof_type + }.payload + }.map_int32_int64 + } + CONSTANT [8] { value: 1 } + } + } + } + } + CALL [9] { + function: _==_ + args: { + CALL [10] { + function: _+_ + args: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @index0 + } + IDENT [13] { + name: @index0 + } + } + } + IDENT [14] { + name: @index0 + } + } + } + CONSTANT [15] { value: 15 } + } + } + } +} +Test case: SELECT_NESTED_MESSAGE_MAP_INDEX_2 +Source: msg.oneof_type.payload.map_int32_int64[0] + msg.oneof_type.payload.map_int32_int64[1] + msg.oneof_type.payload.map_int32_int64[2] == 8 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + SELECT [5] { + IDENT [6] { + name: msg + }.oneof_type + }.payload + }.map_int32_int64 + } + } + } + CALL [7] { + function: _==_ + args: { + CALL [8] { + function: _+_ + args: { + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _[_] + args: { + IDENT [11] { + name: @index0 + } + CONSTANT [12] { value: 0 } + } + } + CALL [13] { + function: _[_] + args: { + IDENT [14] { + name: @index0 + } + CONSTANT [15] { value: 1 } + } + } + } + } + CALL [16] { + function: _[_] + args: { + IDENT [17] { + name: @index0 + } + CONSTANT [18] { value: 2 } + } + } + } + } + CONSTANT [19] { value: 8 } + } + } + } +} +Test case: SELECT_NESTED_NO_COMMON_SUBEXPR +Source: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 +=====> +SELECT [10] { + SELECT [9] { + SELECT [8] { + SELECT [7] { + SELECT [6] { + SELECT [5] { + SELECT [4] { + SELECT [3] { + SELECT [2] { + IDENT [1] { + name: msg + }.oneof_type + }.payload + }.oneof_type + }.payload + }.oneof_type + }.payload + }.oneof_type + }.payload + }.single_int64 +} +Test case: TERNARY +Source: (msg.single_int64 > 0 ? msg.single_int64 : 0) == 3 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.single_int64 + } + } + } + CALL [5] { + function: _==_ + args: { + CALL [6] { + function: _?_:_ + args: { + CALL [7] { + function: _>_ + args: { + IDENT [8] { + name: @index0 + } + CONSTANT [9] { value: 0 } + } + } + IDENT [10] { + name: @index0 + } + CONSTANT [11] { value: 0 } + } + } + CONSTANT [12] { value: 3 } + } + } + } +} +Test case: TERNARY_BIND_RHS_ONLY +Source: false ? false : (msg.single_int64) + ((msg.single_int64 + 1) * 2) == 11 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.single_int64 + } + } + } + CALL [5] { + function: _?_:_ + args: { + CONSTANT [6] { value: false } + CONSTANT [7] { value: false } + CALL [8] { + function: _==_ + args: { + CALL [9] { + function: _+_ + args: { + IDENT [10] { + name: @index0 + } + CALL [11] { + function: _*_ + args: { + CALL [12] { + function: _+_ + args: { + IDENT [13] { + name: @index0 + } + CONSTANT [14] { value: 1 } + } + } + CONSTANT [15] { value: 2 } + } + } + } + } + CONSTANT [16] { value: 11 } + } + } + } + } + } +} +Test case: NESTED_TERNARY +Source: (msg.single_int64 > 0 ? (msg.single_int32 > 0 ? msg.single_int64 + msg.single_int32 : 0) : 0) == 8 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.single_int64 + } + SELECT [5] { + IDENT [6] { + name: msg + }.single_int32 + } + } + } + CALL [7] { + function: _==_ + args: { + CALL [8] { + function: _?_:_ + args: { + CALL [9] { + function: _>_ + args: { + IDENT [10] { + name: @index0 + } + CONSTANT [11] { value: 0 } + } + } + CALL [12] { + function: _?_:_ + args: { + CALL [13] { + function: _>_ + args: { + IDENT [14] { + name: @index1 + } + CONSTANT [15] { value: 0 } + } + } + CALL [16] { + function: _+_ + args: { + IDENT [17] { + name: @index0 + } + IDENT [18] { + name: @index1 + } + } + } + CONSTANT [19] { value: 0 } + } + } + CONSTANT [20] { value: 0 } + } + } + CONSTANT [21] { value: 8 } + } + } + } +} +Test case: MULTIPLE_MACROS_1 +Source: size([[1].exists(i, i > 0)]) + size([[1].exists(j, j > 0)]) + size([[2].exists(k, k > 1)]) + size([[2].exists(l, l > 1)]) == 4 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + CALL [16] { + function: size + args: { + LIST [17] { + elements: { + IDENT [18] { + name: @index0 + } + } + } + } + } + COMPREHENSION [19] { + iter_var: @it:0:0 + iter_range: { + LIST [20] { + elements: { + CONSTANT [21] { value: 2 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [22] { value: false } + } + loop_condition: { + CALL [23] { + function: @not_strictly_false + args: { + CALL [24] { + function: !_ + args: { + IDENT [25] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [26] { + function: _||_ + args: { + IDENT [27] { + name: @ac:0:0 + } + CALL [28] { + function: _>_ + args: { + IDENT [29] { + name: @it:0:0 + } + CONSTANT [30] { value: 1 } + } + } + } + } + } + result: { + IDENT [31] { + name: @ac:0:0 + } + } + } + CALL [32] { + function: size + args: { + LIST [33] { + elements: { + IDENT [34] { + name: @index2 + } + } + } + } + } + } + } + CALL [35] { + function: _==_ + args: { + CALL [36] { + function: _+_ + args: { + CALL [37] { + function: _+_ + args: { + CALL [38] { + function: _+_ + args: { + IDENT [39] { + name: @index1 + } + IDENT [40] { + name: @index1 + } + } + } + IDENT [41] { + name: @index3 + } + } + } + IDENT [42] { + name: @index3 + } + } + } + CONSTANT [43] { value: 4 } + } + } + } +} +Test case: MULTIPLE_MACROS_2 +Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == 'a')] + [['a'].exists(l, l == 'a')] == [true, true, true, true] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + LIST [16] { + elements: { + IDENT [17] { + name: @index0 + } + } + } + COMPREHENSION [18] { + iter_var: @it:0:1 + iter_range: { + LIST [19] { + elements: { + CONSTANT [20] { value: "a" } + } + } + } + accu_var: @ac:0:1 + accu_init: { + CONSTANT [21] { value: false } + } + loop_condition: { + CALL [22] { + function: @not_strictly_false + args: { + CALL [23] { + function: !_ + args: { + IDENT [24] { + name: @ac:0:1 + } + } + } + } + } + } + loop_step: { + CALL [25] { + function: _||_ + args: { + IDENT [26] { + name: @ac:0:1 + } + CALL [27] { + function: _==_ + args: { + IDENT [28] { + name: @it:0:1 + } + CONSTANT [29] { value: "a" } + } + } + } + } + } + result: { + IDENT [30] { + name: @ac:0:1 + } + } + } + LIST [31] { + elements: { + IDENT [32] { + name: @index2 + } + } + } + } + } + CALL [33] { + function: _==_ + args: { + CALL [34] { + function: _+_ + args: { + CALL [35] { + function: _+_ + args: { + CALL [36] { + function: _+_ + args: { + IDENT [37] { + name: @index1 + } + IDENT [38] { + name: @index1 + } + } + } + IDENT [39] { + name: @index3 + } + } + } + IDENT [40] { + name: @index3 + } + } + } + LIST [41] { + elements: { + CONSTANT [42] { value: true } + CONSTANT [43] { value: true } + CONSTANT [44] { value: true } + CONSTANT [45] { value: true } + } + } + } + } + } +} +Test case: MULTIPLE_MACROS_3 +Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && [2].exists(l, l > 1) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + COMPREHENSION [3] { + iter_var: @it:0:0 + iter_range: { + LIST [4] { + elements: { + CONSTANT [5] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [6] { value: false } + } + loop_condition: { + CALL [7] { + function: @not_strictly_false + args: { + CALL [8] { + function: !_ + args: { + IDENT [9] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [10] { + function: _||_ + args: { + IDENT [11] { + name: @ac:0:0 + } + CALL [12] { + function: _>_ + args: { + IDENT [13] { + name: @it:0:0 + } + CONSTANT [14] { value: 0 } + } + } + } + } + } + result: { + IDENT [15] { + name: @ac:0:0 + } + } + } + } + } + CALL [16] { + function: _&&_ + args: { + CALL [17] { + function: _&&_ + args: { + IDENT [18] { + name: @index0 + } + IDENT [19] { + name: @index0 + } + } + } + CALL [20] { + function: _&&_ + args: { + COMPREHENSION [21] { + iter_var: @it:0:0 + iter_range: { + LIST [22] { + elements: { + CONSTANT [23] { value: 1 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [24] { value: false } + } + loop_condition: { + CALL [25] { + function: @not_strictly_false + args: { + CALL [26] { + function: !_ + args: { + IDENT [27] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [28] { + function: _||_ + args: { + IDENT [29] { + name: @ac:0:0 + } + CALL [30] { + function: _>_ + args: { + IDENT [31] { + name: @it:0:0 + } + CONSTANT [32] { value: 1 } + } + } + } + } + } + result: { + IDENT [33] { + name: @ac:0:0 + } + } + } + COMPREHENSION [34] { + iter_var: @it:0:0 + iter_range: { + LIST [35] { + elements: { + CONSTANT [36] { value: 2 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [37] { value: false } + } + loop_condition: { + CALL [38] { + function: @not_strictly_false + args: { + CALL [39] { + function: !_ + args: { + IDENT [40] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [41] { + function: _||_ + args: { + IDENT [42] { + name: @ac:0:0 + } + CALL [43] { + function: _>_ + args: { + IDENT [44] { + name: @it:0:0 + } + CONSTANT [45] { value: 1 } + } + } + } + } + } + result: { + IDENT [46] { + name: @ac:0:0 + } + } + } + } + } + } + } + } +} +Test case: NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [[2, 3, 4], [2, 3, 4], [2, 3, 4]] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + LIST [7] { + elements: { + CONSTANT [8] { value: 2 } + CONSTANT [9] { value: 3 } + CONSTANT [10] { value: 4 } + } + } + } + } + CALL [11] { + function: _==_ + args: { + COMPREHENSION [12] { + iter_var: @it:0:0 + iter_range: { + IDENT [13] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [14] { + elements: { + } + } + } + loop_condition: { + CONSTANT [15] { value: true } + } + loop_step: { + CALL [16] { + function: _+_ + args: { + IDENT [17] { + name: @ac:0:0 + } + LIST [18] { + elements: { + COMPREHENSION [19] { + iter_var: @it:1:0 + iter_range: { + IDENT [20] { + name: @index0 + } + } + accu_var: @ac:1:0 + accu_init: { + LIST [21] { + elements: { + } + } + } + loop_condition: { + CONSTANT [22] { value: true } + } + loop_step: { + CALL [23] { + function: _+_ + args: { + IDENT [24] { + name: @ac:1:0 + } + LIST [25] { + elements: { + CALL [26] { + function: _+_ + args: { + IDENT [27] { + name: @it:1:0 + } + CONSTANT [28] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [29] { + name: @ac:1:0 + } + } + } + } + } + } + } + } + result: { + IDENT [30] { + name: @ac:0:0 + } + } + } + LIST [31] { + elements: { + IDENT [32] { + name: @index1 + } + IDENT [33] { + name: @index1 + } + IDENT [34] { + name: @index1 + } + } + } + } + } + } +} +Test case: NESTED_MACROS_2 +Source: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] +=====> +CALL [31] { + function: _==_ + args: { + COMPREHENSION [30] { + iter_var: @it:0:0 + iter_range: { + LIST [1] { + elements: { + CONSTANT [2] { value: 1 } + CONSTANT [3] { value: 2 } + } + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [24] { + elements: { + } + } + } + loop_condition: { + CONSTANT [25] { value: true } + } + loop_step: { + CALL [28] { + function: _+_ + args: { + IDENT [26] { + name: @ac:0:0 + } + LIST [27] { + elements: { + COMPREHENSION [23] { + iter_var: @it:1:0 + iter_range: { + LIST [6] { + elements: { + CONSTANT [7] { value: 1 } + CONSTANT [8] { value: 2 } + CONSTANT [9] { value: 3 } + } + } + } + accu_var: @ac:1:0 + accu_init: { + LIST [15] { + elements: { + } + } + } + loop_condition: { + CONSTANT [16] { value: true } + } + loop_step: { + CALL [21] { + function: _?_:_ + args: { + CALL [13] { + function: _==_ + args: { + IDENT [12] { + name: @it:1:0 + } + IDENT [14] { + name: @it:0:0 + } + } + } + CALL [19] { + function: _+_ + args: { + IDENT [17] { + name: @ac:1:0 + } + LIST [18] { + elements: { + IDENT [11] { + name: @it:1:0 + } + } + } + } + } + IDENT [20] { + name: @ac:1:0 + } + } + } + } + result: { + IDENT [22] { + name: @ac:1:0 + } + } + } + } + } + } + } + } + result: { + IDENT [29] { + name: @ac:0:0 + } + } + } + LIST [32] { + elements: { + LIST [33] { + elements: { + CONSTANT [34] { value: 1 } + } + } + LIST [35] { + elements: { + CONSTANT [36] { value: 2 } + } + } + } + } + } +} +Test case: ADJACENT_NESTED_MACROS +Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map(j, j + 1)) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + COMPREHENSION [7] { + iter_var: @it:0:0 + iter_range: { + IDENT [8] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [9] { + elements: { + } + } + } + loop_condition: { + CONSTANT [10] { value: true } + } + loop_step: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @ac:0:0 + } + LIST [13] { + elements: { + COMPREHENSION [14] { + iter_var: @it:1:0 + iter_range: { + IDENT [15] { + name: @index0 + } + } + accu_var: @ac:1:0 + accu_init: { + LIST [16] { + elements: { + } + } + } + loop_condition: { + CONSTANT [17] { value: true } + } + loop_step: { + CALL [18] { + function: _+_ + args: { + IDENT [19] { + name: @ac:1:0 + } + LIST [20] { + elements: { + CALL [21] { + function: _+_ + args: { + IDENT [22] { + name: @it:1:0 + } + CONSTANT [23] { value: 1 } + } + } + } + } + } + } + } + result: { + IDENT [24] { + name: @ac:1:0 + } + } + } + } + } + } + } + } + result: { + IDENT [25] { + name: @ac:0:0 + } + } + } + } + } + CALL [26] { + function: _==_ + args: { + IDENT [27] { + name: @index1 + } + IDENT [28] { + name: @index1 + } + } + } + } +} +Test case: INCLUSION_LIST +Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + CONSTANT [6] { value: 3 } + } + } + CALL [7] { + function: @in + args: { + CONSTANT [8] { value: 1 } + IDENT [9] { + name: @index0 + } + } + } + } + } + CALL [10] { + function: _&&_ + args: { + CALL [11] { + function: _&&_ + args: { + IDENT [12] { + name: @index1 + } + CALL [13] { + function: @in + args: { + CONSTANT [14] { value: 2 } + IDENT [15] { + name: @index0 + } + } + } + } + } + CALL [16] { + function: _&&_ + args: { + CALL [17] { + function: @in + args: { + CONSTANT [18] { value: 3 } + LIST [19] { + elements: { + CONSTANT [20] { value: 3 } + IDENT [21] { + name: @index0 + } + } + } + } + } + IDENT [22] { + name: @index1 + } + } + } + } + } + } +} +Test case: INCLUSION_MAP +Source: 2 in {'a': 1, 2: {true: false}, 3: {true: false}} +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: true } + } + value: { + CONSTANT [6] { value: false } + } + } + } + } + } + CALL [7] { + function: @in + args: { + CONSTANT [8] { value: 2 } + MAP [9] { + MAP_ENTRY [10] { + key: { + CONSTANT [11] { value: "a" } + } + value: { + CONSTANT [12] { value: 1 } + } + } + MAP_ENTRY [13] { + key: { + CONSTANT [14] { value: 2 } + } + value: { + IDENT [15] { + name: @index0 + } + } + } + MAP_ENTRY [16] { + key: { + CONSTANT [17] { value: 3 } + } + value: { + IDENT [18] { + name: @index0 + } + } + } + } + } + } + } +} +Test case: MACRO_ITER_VAR_NOT_REFERENCED +Source: [1,2].map(i, [1, 2].map(i, [3,4])) == [[[3, 4], [3, 4]], [[3, 4], [3, 4]]] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + LIST [3] { + elements: { + CONSTANT [4] { value: 1 } + CONSTANT [5] { value: 2 } + } + } + LIST [6] { + elements: { + CONSTANT [7] { value: 3 } + CONSTANT [8] { value: 4 } + } + } + LIST [9] { + elements: { + IDENT [10] { + name: @index1 + } + IDENT [11] { + name: @index1 + } + } + } + } + } + CALL [12] { + function: _==_ + args: { + COMPREHENSION [13] { + iter_var: @it:0:0 + iter_range: { + IDENT [14] { + name: @index0 + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [15] { + elements: { + } + } + } + loop_condition: { + CONSTANT [16] { value: true } + } + loop_step: { + CALL [17] { + function: _+_ + args: { + IDENT [18] { + name: @ac:0:0 + } + LIST [19] { + elements: { + COMPREHENSION [20] { + iter_var: @it:1:0 + iter_range: { + IDENT [21] { + name: @index0 + } + } + accu_var: @ac:1:0 + accu_init: { + LIST [22] { + elements: { + } + } + } + loop_condition: { + CONSTANT [23] { value: true } + } + loop_step: { + CALL [24] { + function: _+_ + args: { + IDENT [25] { + name: @ac:1:0 + } + LIST [26] { + elements: { + IDENT [27] { + name: @index1 + } + } + } + } + } + } + result: { + IDENT [28] { + name: @ac:1:0 + } + } + } + } + } + } + } + } + result: { + IDENT [29] { + name: @ac:0:0 + } + } + } + LIST [30] { + elements: { + IDENT [31] { + name: @index2 + } + IDENT [32] { + name: @index2 + } + } + } + } + } + } +} +Test case: MACRO_SHADOWED_VARIABLE +Source: [x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _-_ + args: { + IDENT [4] { + name: x + } + CONSTANT [5] { value: 1 } + } + } + CALL [6] { + function: _>_ + args: { + IDENT [7] { + name: @index0 + } + CONSTANT [8] { value: 3 } + } + } + } + } + CALL [9] { + function: _||_ + args: { + COMPREHENSION [10] { + iter_var: @it:0:0 + iter_range: { + LIST [11] { + elements: { + CALL [12] { + function: _?_:_ + args: { + IDENT [13] { + name: @index1 + } + IDENT [14] { + name: @index0 + } + CONSTANT [15] { value: 5 } + } + } + } + } + } + accu_var: @ac:0:0 + accu_init: { + CONSTANT [16] { value: false } + } + loop_condition: { + CALL [17] { + function: @not_strictly_false + args: { + CALL [18] { + function: !_ + args: { + IDENT [19] { + name: @ac:0:0 + } + } + } + } + } + } + loop_step: { + CALL [20] { + function: _||_ + args: { + IDENT [21] { + name: @ac:0:0 + } + CALL [22] { + function: _>_ + args: { + CALL [23] { + function: _-_ + args: { + IDENT [24] { + name: @it:0:0 + } + CONSTANT [25] { value: 1 } + } + } + CONSTANT [26] { value: 3 } + } + } + } + } + } + result: { + IDENT [27] { + name: @ac:0:0 + } + } + } + IDENT [28] { + name: @index1 + } + } + } + } +} +Test case: MACRO_SHADOWED_VARIABLE_2 +Source: ["foo", "bar"].map(x, [x + x, x + x]).map(x, [x + x, x + x]) +=====> +COMPREHENSION [35] { + iter_var: @it:0:0 + iter_range: { + COMPREHENSION [19] { + iter_var: @it:1:0 + iter_range: { + LIST [1] { + elements: { + CONSTANT [2] { value: "foo" } + CONSTANT [3] { value: "bar" } + } + } + } + accu_var: @ac:1:0 + accu_init: { + LIST [13] { + elements: { + } + } + } + loop_condition: { + CONSTANT [14] { value: true } + } + loop_step: { + CALL [17] { + function: _+_ + args: { + IDENT [15] { + name: @ac:1:0 + } + LIST [16] { + elements: { + LIST [6] { + elements: { + CALL [8] { + function: _+_ + args: { + IDENT [7] { + name: @it:1:0 + } + IDENT [9] { + name: @it:1:0 + } + } + } + CALL [11] { + function: _+_ + args: { + IDENT [10] { + name: @it:1:0 + } + IDENT [12] { + name: @it:1:0 + } + } + } + } + } + } + } + } + } + } + result: { + IDENT [18] { + name: @ac:1:0 + } + } + } + } + accu_var: @ac:0:0 + accu_init: { + LIST [29] { + elements: { + } + } + } + loop_condition: { + CONSTANT [30] { value: true } + } + loop_step: { + CALL [33] { + function: _+_ + args: { + IDENT [31] { + name: @ac:0:0 + } + LIST [32] { + elements: { + LIST [22] { + elements: { + CALL [24] { + function: _+_ + args: { + IDENT [23] { + name: @it:0:0 + } + IDENT [25] { + name: @it:0:0 + } + } + } + CALL [27] { + function: _+_ + args: { + IDENT [26] { + name: @it:0:0 + } + IDENT [28] { + name: @it:0:0 + } + } + } + } + } + } + } + } + } + } + result: { + IDENT [34] { + name: @ac:0:0 + } + } +} +Test case: PRESENCE_TEST +Source: has({'a': true}.a) && {'a':true}['a'] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + CALL [10] { + function: _[_] + args: { + IDENT [11] { + name: @index0 + } + CONSTANT [12] { value: "a" } + } + } + } + } + } +} +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + MAP [4] { + MAP_ENTRY [5] { + key: { + CONSTANT [6] { value: "a" } + } + value: { + CONSTANT [7] { value: true } + } + } + }.a~presence_test + } + } + } + CALL [8] { + function: _&&_ + args: { + IDENT [9] { + name: @index0 + } + IDENT [10] { + name: @index0 + } + } + } + } +} +Test case: PRESENCE_TEST_WITH_TERNARY +Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + } + } + CALL [5] { + function: _==_ + args: { + CALL [6] { + function: _?_:_ + args: { + SELECT [7] { + IDENT [8] { + name: @index0 + }.payload~presence_test + } + SELECT [9] { + SELECT [10] { + IDENT [11] { + name: @index0 + }.payload + }.single_int64 + } + CONSTANT [12] { value: 0 } + } + } + CONSTANT [13] { value: 10 } + } + } + } +} +Test case: PRESENCE_TEST_WITH_TERNARY_2 +Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : msg.oneof_type.payload.single_int64 * 0) == 10 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + SELECT [6] { + IDENT [7] { + name: @index0 + }.payload + }.single_int64 + } + } + } + CALL [8] { + function: _==_ + args: { + CALL [9] { + function: _?_:_ + args: { + SELECT [10] { + IDENT [11] { + name: @index0 + }.payload~presence_test + } + IDENT [12] { + name: @index1 + } + CALL [13] { + function: _*_ + args: { + IDENT [14] { + name: @index1 + } + CONSTANT [15] { value: 0 } + } + } + } + } + CONSTANT [16] { value: 10 } + } + } + } +} +Test case: PRESENCE_TEST_WITH_TERNARY_3 +Source: (has(msg.oneof_type.payload.single_int64) ? msg.oneof_type.payload.single_int64 : msg.oneof_type.payload.single_int64 * 0) == 10 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + SELECT [6] { + IDENT [7] { + name: @index0 + }.single_int64 + } + } + } + CALL [8] { + function: _==_ + args: { + CALL [9] { + function: _?_:_ + args: { + SELECT [10] { + IDENT [11] { + name: @index0 + }.single_int64~presence_test + } + IDENT [12] { + name: @index1 + } + CALL [13] { + function: _*_ + args: { + IDENT [14] { + name: @index1 + } + CONSTANT [15] { value: 0 } + } + } + } + } + CONSTANT [16] { value: 10 } + } + } + } +} +Test case: PRESENCE_TEST_WITH_TERNARY_NESTED +Source: (has(msg.oneof_type) && has(msg.oneof_type.payload) && has(msg.oneof_type.payload.single_int64)) ? ((has(msg.oneof_type.payload.map_string_string) && has(msg.oneof_type.payload.map_string_string.key)) ? msg.oneof_type.payload.map_string_string.key == 'A' : false) : false +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + IDENT [4] { + name: msg + }.oneof_type + } + SELECT [5] { + IDENT [6] { + name: @index0 + }.payload + } + SELECT [7] { + IDENT [8] { + name: @index1 + }.map_string_string + } + } + } + CALL [9] { + function: _?_:_ + args: { + CALL [10] { + function: _&&_ + args: { + CALL [11] { + function: _&&_ + args: { + SELECT [12] { + IDENT [13] { + name: msg + }.oneof_type~presence_test + } + SELECT [14] { + IDENT [15] { + name: @index0 + }.payload~presence_test + } + } + } + SELECT [16] { + IDENT [17] { + name: @index1 + }.single_int64~presence_test + } + } + } + CALL [18] { + function: _?_:_ + args: { + CALL [19] { + function: _&&_ + args: { + SELECT [20] { + IDENT [21] { + name: @index1 + }.map_string_string~presence_test + } + SELECT [22] { + IDENT [23] { + name: @index2 + }.key~presence_test + } + } + } + CALL [24] { + function: _==_ + args: { + SELECT [25] { + IDENT [26] { + name: @index2 + }.key + } + CONSTANT [27] { value: "A" } + } + } + CONSTANT [28] { value: false } + } + } + CONSTANT [29] { value: false } + } + } + } +} +Test case: OPTIONAL_LIST +Source: [10, ?optional.none(), [?optional.none(), ?opt_x], [?optional.none(), ?opt_x]] == [10, [5], [5]] +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: optional.none + args: { + } + } + LIST [4] { + elements: { + IDENT [5] { + name: @index0 + } + IDENT [6] { + name: opt_x + } + } + optional_indices: [0, 1] + } + LIST [7] { + elements: { + CONSTANT [8] { value: 5 } + } + } + } + } + CALL [9] { + function: _==_ + args: { + LIST [10] { + elements: { + CONSTANT [11] { value: 10 } + IDENT [12] { + name: @index0 + } + IDENT [13] { + name: @index1 + } + IDENT [14] { + name: @index1 + } + } + optional_indices: [0] + } + LIST [15] { + elements: { + CONSTANT [16] { value: 10 } + IDENT [17] { + name: @index2 + } + IDENT [18] { + name: @index2 + } + } + } + } + } + } +} +Test case: OPTIONAL_MAP +Source: {?'hello': optional.of('hello')}['hello'] + {?'hello': optional.of('hello')}['hello'] == 'hellohello' +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _[_] + args: { + MAP [4] { + MAP_ENTRY [5] { + key: { + CONSTANT [6] { value: "hello" } + } + optional_entry: true + value: { + CALL [7] { + function: optional.of + args: { + CONSTANT [8] { value: "hello" } + } + } + } + } + } + CONSTANT [9] { value: "hello" } + } + } + } + } + CALL [10] { + function: _==_ + args: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @index0 + } + IDENT [13] { + name: @index0 + } + } + } + CONSTANT [14] { value: "hellohello" } + } + } + } +} +Test case: OPTIONAL_MAP_CHAINED +Source: {?'key': optional.of('test')}[?'bogus'].or({'key': 'test'}[?'bogus']).orValue({'key': 'test'}['key']) == 'test' +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "key" } + } + value: { + CONSTANT [6] { value: "test" } + } + } + } + } + } + CALL [7] { + function: _==_ + args: { + CALL [8] { + function: orValue + target: { + CALL [9] { + function: or + target: { + CALL [10] { + function: _[?_] + args: { + MAP [11] { + MAP_ENTRY [12] { + key: { + CONSTANT [13] { value: "key" } + } + optional_entry: true + value: { + CALL [14] { + function: optional.of + args: { + CONSTANT [15] { value: "test" } + } + } + } + } + } + CONSTANT [16] { value: "bogus" } + } + } + } + args: { + CALL [17] { + function: _[?_] + args: { + IDENT [18] { + name: @index0 + } + CONSTANT [19] { value: "bogus" } + } + } + } + } + } + args: { + CALL [20] { + function: _[_] + args: { + IDENT [21] { + name: @index0 + } + CONSTANT [22] { value: "key" } + } + } + } + } + CONSTANT [23] { value: "test" } + } + } + } +} +Test case: OPTIONAL_MESSAGE +Source: TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}.single_int32 + TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}.single_int64 == 5 +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + STRUCT [3] { + name: TestAllTypes + entries: { + ENTRY [4] { + field_key: single_int64 + optional_entry: true + value: { + CALL [5] { + function: optional.ofNonZeroValue + args: { + CONSTANT [6] { value: 1 } + } + } + } + } + ENTRY [7] { + field_key: single_int32 + optional_entry: true + value: { + CALL [8] { + function: optional.of + args: { + CONSTANT [9] { value: 4 } + } + } + } + } + } + } + } + } + CALL [10] { + function: _==_ + args: { + CALL [11] { + function: _+_ + args: { + SELECT [12] { + IDENT [13] { + name: @index0 + }.single_int32 + } + SELECT [14] { + IDENT [15] { + name: @index0 + }.single_int64 + } + } + } + CONSTANT [16] { value: 5 } + } + } + } +} +Test case: CALL +Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('h' + 'e' + 'l' + 'l' + 'o') +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + CALL [3] { + function: _+_ + args: { + CALL [4] { + function: _+_ + args: { + CALL [5] { + function: _+_ + args: { + CALL [6] { + function: _+_ + args: { + CONSTANT [7] { value: "h" } + CONSTANT [8] { value: "e" } + } + } + CONSTANT [9] { value: "l" } + } + } + CONSTANT [10] { value: "l" } + } + } + CONSTANT [11] { value: "o" } + } + } + } + } + CALL [12] { + function: matches + target: { + CALL [13] { + function: _+_ + args: { + IDENT [14] { + name: @index0 + } + CONSTANT [15] { value: " world" } + } + } + } + args: { + IDENT [16] { + name: @index0 + } + } + } + } +} +Test case: CALL_ARGUMENT_NESTED_NO_COMMON_SUBEXPR +Source: 'hello world'.matches('h' + 'e' + 'l' + 'l' + 'o') +=====> +CALL [2] { + function: matches + target: { + CONSTANT [1] { value: "hello world" } + } + args: { + CALL [10] { + function: _+_ + args: { + CALL [8] { + function: _+_ + args: { + CALL [6] { + function: _+_ + args: { + CALL [4] { + function: _+_ + args: { + CONSTANT [3] { value: "h" } + CONSTANT [5] { value: "e" } + } + } + CONSTANT [7] { value: "l" } + } + } + CONSTANT [9] { value: "l" } + } + } + CONSTANT [11] { value: "o" } + } + } + } +} +Test case: CALL_TARGET_NESTED_NO_COMMON_SUBEXPR +Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('hello') +=====> +CALL [12] { + function: matches + target: { + CALL [10] { + function: _+_ + args: { + CALL [8] { + function: _+_ + args: { + CALL [6] { + function: _+_ + args: { + CALL [4] { + function: _+_ + args: { + CALL [2] { + function: _+_ + args: { + CONSTANT [1] { value: "h" } + CONSTANT [3] { value: "e" } + } + } + CONSTANT [5] { value: "l" } + } + } + CONSTANT [7] { value: "l" } + } + } + CONSTANT [9] { value: "o" } + } + } + CONSTANT [11] { value: " world" } + } + } + } + args: { + CONSTANT [13] { value: "hello" } + } +} +Test case: CALL_BOTH_ARGUMENT_TARGET_NESTED_NO_COMMON_SUBEXPR +Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('w' + 'o' + 'r' + 'l' + 'd') +=====> +CALL [12] { + function: matches + target: { + CALL [10] { + function: _+_ + args: { + CALL [8] { + function: _+_ + args: { + CALL [6] { + function: _+_ + args: { + CALL [4] { + function: _+_ + args: { + CALL [2] { + function: _+_ + args: { + CONSTANT [1] { value: "h" } + CONSTANT [3] { value: "e" } + } + } + CONSTANT [5] { value: "l" } + } + } + CONSTANT [7] { value: "l" } + } + } + CONSTANT [9] { value: "o" } + } + } + CONSTANT [11] { value: " world" } + } + } + } + args: { + CALL [20] { + function: _+_ + args: { + CALL [18] { + function: _+_ + args: { + CALL [16] { + function: _+_ + args: { + CALL [14] { + function: _+_ + args: { + CONSTANT [13] { value: "w" } + CONSTANT [15] { value: "o" } + } + } + CONSTANT [17] { value: "r" } + } + } + CONSTANT [19] { value: "l" } + } + } + CONSTANT [21] { value: "d" } + } + } + } +} +Test case: CUSTOM_FUNCTION_INELIMINABLE +Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + SELECT [6] { + IDENT [7] { + name: @index0 + }.single_int64 + } + } + } + CALL [8] { + function: _+_ + args: { + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + CALL [11] { + function: non_pure_custom_func + args: { + IDENT [12] { + name: @index1 + } + } + } + CALL [13] { + function: non_pure_custom_func + args: { + SELECT [14] { + IDENT [15] { + name: @index0 + }.single_int32 + } + } + } + } + } + CALL [16] { + function: non_pure_custom_func + args: { + IDENT [17] { + name: @index1 + } + } + } + } + } + CALL [18] { + function: non_pure_custom_func + args: { + SELECT [19] { + IDENT [20] { + name: msg + }.single_int64 + } + } + } + } + } + } +} +Test case: CUSTOM_FUNCTION_ELIMINABLE +Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.oneof_type.payload.single_int32) + pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func(msg.single_int64) +=====> +CALL [1] { + function: cel.@block + args: { + LIST [2] { + elements: { + SELECT [3] { + SELECT [4] { + IDENT [5] { + name: msg + }.oneof_type + }.payload + } + CALL [6] { + function: pure_custom_func + args: { + SELECT [7] { + IDENT [8] { + name: @index0 + }.single_int64 + } + } + } + } + } + CALL [9] { + function: _+_ + args: { + CALL [10] { + function: _+_ + args: { + CALL [11] { + function: _+_ + args: { + IDENT [12] { + name: @index1 + } + CALL [13] { + function: pure_custom_func + args: { + SELECT [14] { + IDENT [15] { + name: @index0 + }.single_int32 + } + } + } + } + } + IDENT [16] { + name: @index1 + } + } + } + CALL [17] { + function: pure_custom_func + args: { + SELECT [18] { + IDENT [19] { + name: msg + }.single_int64 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/optimizer/src/test/resources/subexpression_unparsed.baseline b/optimizer/src/test/resources/subexpression_unparsed.baseline index 781f59990..6b8606a48 100644 --- a/optimizer/src/test/resources/subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/subexpression_unparsed.baseline @@ -4,6 +4,7 @@ Source: size([1,2]) + size([1,2]) + 1 == 5 Result: true [CASCADED_BINDS]: cel.bind(@r0, size([1, 2]), @r0 + @r0) + 1 == 5 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([size([1, 2])], @index0 + @index0 + 1 == 5) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([size([1, 2])], @index0 + @index0 + 1 == 5) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], size(@index0), @index1 + @index1, @index2 + 1], @index3 == 5) [BLOCK_RECURSION_DEPTH_2]: cel.@block([size([1, 2]), @index0 + @index0 + 1], @index1 == 5) [BLOCK_RECURSION_DEPTH_3]: cel.@block([size([1, 2])], @index0 + @index0 + 1 == 5) @@ -20,6 +21,7 @@ Source: 2 + size([1,2]) + size([1,2]) + 1 == 7 Result: true [CASCADED_BINDS]: cel.bind(@r0, size([1, 2]), 2 + @r0 + @r0) + 1 == 7 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([size([1, 2])], 2 + @index0 + @index0 + 1 == 7) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([size([1, 2])], 2 + @index0 + @index0 + 1 == 7) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], size(@index0), 2 + @index1, @index2 + @index1, @index3 + 1], @index4 == 7) [BLOCK_RECURSION_DEPTH_2]: cel.@block([size([1, 2]), 2 + @index0 + @index0], @index1 + 1 == 7) [BLOCK_RECURSION_DEPTH_3]: cel.@block([size([1, 2]), 2 + @index0 + @index0 + 1], @index1 == 7) @@ -36,6 +38,7 @@ Source: size([0]) + size([0]) + size([1,2]) + size([1,2]) == 6 Result: true [CASCADED_BINDS]: cel.bind(@r1, size([1, 2]), cel.bind(@r0, size([0]), @r0 + @r0) + @r1 + @r1) == 6 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([size([0]), size([1, 2])], @index0 + @index0 + @index1 + @index1 == 6) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([size([0]), size([1, 2])], @index0 + @index0 + @index1 + @index1 == 6) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[0], size(@index0), [1, 2], size(@index2), @index1 + @index1, @index4 + @index3, @index5 + @index3], @index6 == 6) [BLOCK_RECURSION_DEPTH_2]: cel.@block([size([0]), size([1, 2]), @index0 + @index0 + @index1], @index2 + @index1 == 6) [BLOCK_RECURSION_DEPTH_3]: cel.@block([size([0]), size([1, 2]), @index0 + @index0 + @index1 + @index1], @index2 == 6) @@ -52,6 +55,7 @@ Source: 5 + size([0]) + size([0]) + size([1,2]) + size([1,2]) + size([1,2,3]) + Result: true [CASCADED_BINDS]: cel.bind(@r2, size([1, 2, 3]), cel.bind(@r1, size([1, 2]), cel.bind(@r0, size([0]), 5 + @r0 + @r0) + @r1 + @r1) + @r2 + @r2) == 17 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([size([0]), size([1, 2]), size([1, 2, 3])], 5 + @index0 + @index0 + @index1 + @index1 + @index2 + @index2 == 17) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([size([0]), size([1, 2]), size([1, 2, 3])], 5 + @index0 + @index0 + @index1 + @index1 + @index2 + @index2 == 17) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[0], size(@index0), [1, 2], size(@index2), [1, 2, 3], size(@index4), 5 + @index1, @index6 + @index1, @index7 + @index3, @index8 + @index3, @index9 + @index5, @index10 + @index5], @index11 == 17) [BLOCK_RECURSION_DEPTH_2]: cel.@block([size([0]), size([1, 2]), size([1, 2, 3]), 5 + @index0 + @index0, @index3 + @index1 + @index1, @index4 + @index2 + @index2], @index5 == 17) [BLOCK_RECURSION_DEPTH_3]: cel.@block([size([0]), size([1, 2]), size([1, 2, 3]), 5 + @index0 + @index0 + @index1, @index3 + @index1 + @index2 + @index2], @index4 == 17) @@ -68,6 +72,7 @@ Source: timestamp(int(timestamp(1000000000))).getFullYear() + timestamp(int(time Result: true [CASCADED_BINDS]: cel.bind(@r0, timestamp(int(timestamp(1000000000))).getFullYear(), cel.bind(@r3, timestamp(int(timestamp(75))), cel.bind(@r2, timestamp(int(timestamp(200))).getFullYear(), cel.bind(@r1, timestamp(int(timestamp(50))), @r0 + @r3.getFullYear() + @r1.getFullYear() + @r0 + @r1.getSeconds()) + @r2 + @r2) + @r3.getMinutes()) + @r0) == 13934 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([timestamp(int(timestamp(1000000000))).getFullYear(), timestamp(int(timestamp(50))), timestamp(int(timestamp(200))).getFullYear(), timestamp(int(timestamp(75)))], @index0 + @index3.getFullYear() + @index1.getFullYear() + @index0 + @index1.getSeconds() + @index2 + @index2 + @index3.getMinutes() + @index0 == 13934) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([timestamp(int(timestamp(1000000000))).getFullYear(), timestamp(int(timestamp(50))), timestamp(int(timestamp(200))).getFullYear(), timestamp(int(timestamp(75)))], @index0 + @index3.getFullYear() + @index1.getFullYear() + @index0 + @index1.getSeconds() + @index2 + @index2 + @index3.getMinutes() + @index0 == 13934) [BLOCK_RECURSION_DEPTH_1]: cel.@block([timestamp(1000000000), int(@index0), timestamp(@index1), @index2.getFullYear(), timestamp(50), int(@index4), timestamp(@index5), timestamp(200), int(@index7), timestamp(@index8), @index9.getFullYear(), timestamp(75), int(@index11), timestamp(@index12), @index13.getFullYear(), @index3 + @index14, @index6.getFullYear(), @index15 + @index16, @index17 + @index3, @index6.getSeconds(), @index18 + @index19, @index20 + @index10, @index21 + @index10, @index13.getMinutes(), @index22 + @index23, @index24 + @index3], @index25 == 13934) [BLOCK_RECURSION_DEPTH_2]: cel.@block([int(timestamp(1000000000)), timestamp(@index0).getFullYear(), int(timestamp(50)), int(timestamp(200)), timestamp(@index3).getFullYear(), int(timestamp(75)), timestamp(@index2), timestamp(@index5), @index1 + @index7.getFullYear(), @index8 + @index6.getFullYear(), @index9 + @index1 + @index6.getSeconds(), @index10 + @index4 + @index4, @index11 + @index7.getMinutes()], @index12 + @index1 == 13934) [BLOCK_RECURSION_DEPTH_3]: cel.@block([timestamp(int(timestamp(1000000000))), timestamp(int(timestamp(50))), timestamp(int(timestamp(200))), timestamp(int(timestamp(75))), @index0.getFullYear(), @index2.getFullYear(), @index4 + @index3.getFullYear() + @index1.getFullYear(), @index6 + @index4 + @index1.getSeconds() + @index5, @index7 + @index5 + @index3.getMinutes() + @index4], @index8 == 13934) @@ -84,6 +89,7 @@ Source: {"a": 2}["a"] + {"a": 2}["a"] * {"a": 2}["a"] == 6 Result: true [CASCADED_BINDS]: cel.bind(@r0, {"a": 2}["a"], @r0 + @r0 * @r0) == 6 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{"a": 2}["a"]], @index0 + @index0 * @index0 == 6) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{"a": 2}["a"]], @index0 + @index0 * @index0 == 6) [BLOCK_RECURSION_DEPTH_1]: cel.@block([{"a": 2}, @index0["a"], @index1 * @index1, @index1 + @index2], @index3 == 6) [BLOCK_RECURSION_DEPTH_2]: cel.@block([{"a": 2}["a"], @index0 + @index0 * @index0], @index1 == 6) [BLOCK_RECURSION_DEPTH_3]: cel.@block([{"a": 2}["a"]], @index0 + @index0 * @index0 == 6) @@ -100,6 +106,7 @@ Source: {'a': {'b': 1}, 'c': {'b': 1}, 'd': {'e': {'b': 1}}, 'e': {'e': {'b': 1} Result: {a={b=1}, c={b=1}, d={e={b=1}}, e={e={b=1}}} [CASCADED_BINDS]: cel.bind(@r0, {"b": 1}, cel.bind(@r1, {"e": @r0}, {"a": @r0, "c": @r0, "d": @r1, "e": @r1})) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{"b": 1}, {"e": @index0}], {"a": @index0, "c": @index0, "d": @index1, "e": @index1}) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{"b": 1}, {"e": @index0}], {"a": @index0, "c": @index0, "d": @index1, "e": @index1}) [BLOCK_RECURSION_DEPTH_1]: cel.@block([{"b": 1}, {"e": @index0}], {"a": @index0, "c": @index0, "d": @index1, "e": @index1}) [BLOCK_RECURSION_DEPTH_2]: cel.@block([{"e": {"b": 1}}, {"b": 1}], {"a": @index1, "c": @index1, "d": @index0, "e": @index0}) [BLOCK_RECURSION_DEPTH_3]: cel.@block([{"e": {"b": 1}}, {"b": 1}], {"a": @index1, "c": @index1, "d": @index0, "e": @index0}) @@ -116,6 +123,7 @@ Source: [1, [1,2,3,4], 2, [1,2,3,4], 5, [1,2,3,4], 7, [[1,2], [1,2,3,4]], [1,2]] Result: [1, [1, 2, 3, 4], 2, [1, 2, 3, 4], 5, [1, 2, 3, 4], 7, [[1, 2], [1, 2, 3, 4]], [1, 2]] [CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3, 4], cel.bind(@r1, [1, 2], [1, @r0, 2, @r0, 5, @r0, 7, [@r1, @r0], @r1])) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3, 4], [1, 2], [@index1, @index0]], [1, @index0, 2, @index0, 5, @index0, 7, @index2, @index1]) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3, 4], [1, 2]], [1, @index0, 2, @index0, 5, @index0, 7, [@index1, @index0], @index1]) @@ -132,6 +140,7 @@ Source: msg.single_int64 + msg.single_int64 == 6 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, @r0 + @r0) == 6 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64], @index0 + @index0 == 6) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64], @index0 + @index0 == 6) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, @index0 + @index0], @index1 == 6) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64], @index0 + @index0 == 6) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64], @index0 + @index0 == 6) @@ -148,6 +157,7 @@ Source: msg.oneof_type.payload.single_int64 + msg.oneof_type.payload.single_int3 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, @r1 + @r0.single_int32 + @r1) + msg.single_int64 + @r0.oneof_type.payload.single_int64) == 31 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], @index1 + @index0.single_int32 + @index1 + msg.single_int64 + @index0.oneof_type.payload.single_int64 == 31) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, @index0.single_int64], @index1 + @index0.single_int32 + @index1 + msg.single_int64 + @index0.oneof_type.payload.single_int64 == 31) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, @index1.single_int32, @index2 + @index3, @index4 + @index2, msg.single_int64, @index5 + @index6, @index1.oneof_type, @index8.payload, @index9.single_int64, @index7 + @index10], @index11 == 31) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64, @index1 + @index0.single_int32, @index2 + @index1 + msg.single_int64, @index0.oneof_type.payload, @index3 + @index4.single_int64], @index5 == 31) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, msg.oneof_type.payload, @index0 + @index1.single_int32 + @index0, @index1.oneof_type.payload.single_int64, @index2 + msg.single_int64 + @index3], @index4 == 31) @@ -164,6 +174,7 @@ Source: true || msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.one Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload.oneof_type.payload.oneof_type, true || @r0.payload.oneof_type.payload.single_bool || @r0.child.child.payload.single_bool) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload.oneof_type.payload.oneof_type], true || @index0.payload.oneof_type.payload.single_bool || @index0.child.child.payload.single_bool) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload.oneof_type.payload.oneof_type], true || @index0.payload.oneof_type.payload.single_bool || @index0.child.child.payload.single_bool) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.oneof_type, @index2.payload, @index3.oneof_type, @index4.payload, @index5.oneof_type, @index6.payload, @index7.single_bool, true || @index8, @index4.child, @index10.child, @index11.payload, @index12.single_bool], @index9 || @index13) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.oneof_type.payload, @index1.oneof_type, @index2.payload.oneof_type, @index3.payload.single_bool, @index2.child.child, @index5.payload.single_bool], true || @index4 || @index6) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.oneof_type, @index0.payload.oneof_type, @index1.payload.oneof_type.payload, @index1.child.child.payload], true || @index2.single_bool || @index3.single_bool) @@ -180,6 +191,7 @@ Source: msg.oneof_type.payload.map_int32_int64[1] + msg.oneof_type.payload.map_i Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload.map_int32_int64[1], @r0 + @r0 + @r0) == 15 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload.map_int32_int64[1]], @index0 + @index0 + @index0 == 15) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload.map_int32_int64[1]], @index0 + @index0 + @index0 == 15) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_int32_int64, @index2[1], @index3 + @index3, @index4 + @index3], @index5 == 15) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.map_int32_int64[1], @index1 + @index1 + @index1], @index2 == 15) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.map_int32_int64, @index0[1]], @index1 + @index1 + @index1 == 15) @@ -196,6 +208,7 @@ Source: msg.oneof_type.payload.map_int32_int64[0] + msg.oneof_type.payload.map_i Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload.map_int32_int64, @r0[0] + @r0[1] + @r0[2]) == 8 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload.map_int32_int64], @index0[0] + @index0[1] + @index0[2] == 8) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload.map_int32_int64], @index0[0] + @index0[1] + @index0[2] == 8) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_int32_int64, @index2[0], @index2[1], @index3 + @index4, @index2[2], @index5 + @index6], @index7 == 8) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.map_int32_int64, @index1[0] + @index1[1], @index2 + @index1[2]], @index3 == 8) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.map_int32_int64, @index0[0] + @index0[1] + @index0[2]], @index1 == 8) @@ -212,6 +225,7 @@ Source: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type. Result: 0 [CASCADED_BINDS]: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 [BLOCK_COMMON_SUBEXPR_ONLY]: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: msg.oneof_type.payload.oneof_type.payload.oneof_type.payload.oneof_type.payload.single_int64 [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.oneof_type, @index2.payload, @index3.oneof_type, @index4.payload, @index5.oneof_type, @index6.payload], @index7.single_int64) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.oneof_type.payload, @index1.oneof_type.payload, @index2.oneof_type.payload], @index3.single_int64) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.oneof_type, @index0.payload.oneof_type.payload], @index1.oneof_type.payload.single_int64) @@ -228,6 +242,7 @@ Source: (msg.single_int64 > 0 ? msg.single_int64 : 0) == 3 Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, (@r0 > 0) ? @r0 : 0) == 3 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64], ((@index0 > 0) ? @index0 : 0) == 3) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64], ((@index0 > 0) ? @index0 : 0) == 3) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, @index0 > 0, @index1 ? @index0 : 0], @index2 == 3) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64, (@index0 > 0) ? @index0 : 0], @index1 == 3) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64], ((@index0 > 0) ? @index0 : 0) == 3) @@ -244,6 +259,7 @@ Source: false ? false : (msg.single_int64) + ((msg.single_int64 + 1) * 2) == 11 Result: true [CASCADED_BINDS]: false ? false : (cel.bind(@r0, msg.single_int64, @r0 + (@r0 + 1) * 2) == 11) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64], false ? false : (@index0 + (@index0 + 1) * 2 == 11)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64], false ? false : (@index0 + (@index0 + 1) * 2 == 11)) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, @index0 + 1, @index1 * 2, @index0 + @index2, @index3 == 11], false ? false : @index4) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64, (@index0 + 1) * 2, @index0 + @index1 == 11], false ? false : @index2) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64, @index0 + (@index0 + 1) * 2], false ? false : (@index1 == 11)) @@ -260,6 +276,7 @@ Source: (msg.single_int64 > 0 ? (msg.single_int32 > 0 ? msg.single_int64 + msg.s Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.single_int64, (@r0 > 0) ? cel.bind(@r1, msg.single_int32, (@r1 > 0) ? (@r0 + @r1) : 0) : 0) == 8 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.single_int64, msg.single_int32], ((@index0 > 0) ? ((@index1 > 0) ? (@index0 + @index1) : 0) : 0) == 8) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.single_int64, msg.single_int32], ((@index0 > 0) ? ((@index1 > 0) ? (@index0 + @index1) : 0) : 0) == 8) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.single_int64, msg.single_int32, @index0 > 0, @index1 > 0, @index0 + @index1, @index3 ? @index4 : 0, @index2 ? @index5 : 0], @index6 == 8) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.single_int64, msg.single_int32, (@index1 > 0) ? (@index0 + @index1) : 0, (@index0 > 0) ? @index2 : 0], @index3 == 8) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.single_int64, msg.single_int32, (@index0 > 0) ? ((@index1 > 0) ? (@index0 + @index1) : 0) : 0], @index2 == 8) @@ -276,6 +293,7 @@ Source: size([[1].exists(i, i > 0)]) + size([[1].exists(j, j > 0)]) + size([[2]. Result: true [CASCADED_BINDS]: cel.bind(@r1, [2], cel.bind(@r0, [1], size([@r0.exists(@it:0, @it:0 > 0)]) + size([@r0.exists(@it:1, @it:1 > 0)])) + size([@r1.exists(@it:2, @it:2 > 1)]) + size([@r1.exists(@it:3, @it:3 > 1)])) == 4 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([size([[1].exists(@it:0:0, @it:0:0 > 0)]), size([[2].exists(@it:0:0, @it:0:0 > 1)])], @index0 + @index0 + @index1 + @index1 == 4) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), size([@index0]), [2].exists(@it:0:0, @it:0:0 > 1), size([@index2])], @index1 + @index1 + @index3 + @index3 == 4) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @it:0:0 > 0, @ac:0:0 || @index1, [2], @it:0:0 > 1, @ac:0:0 || @index4], size([@index0.exists(@it:0:0, @index1)]) + size([@index0.exists(@it:0:0, @index1)]) + size([@index3.exists(@it:0:0, @index4)]) + size([@index3.exists(@it:0:0, @index4)]) == 4) [BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:0:0 || @it:0:0 > 0, @ac:0:0 || @it:0:0 > 1, [1], [2]], size([@index2.exists(@it:0:0, @it:0:0 > 0)]) + size([@index2.exists(@it:0:0, @it:0:0 > 0)]) + size([@index3.exists(@it:0:0, @it:0:0 > 1)]) + size([@index3.exists(@it:0:0, @it:0:0 > 1)]) == 4) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), [2].exists(@it:0:0, @it:0:0 > 1), size([@index0]), size([@index1]), @index2 + @index2 + @index3 + @index3], @index4 == 4) @@ -292,6 +310,7 @@ Source: [[1].exists(i, i > 0)] + [[1].exists(j, j > 0)] + [['a'].exists(k, k == Result: true [CASCADED_BINDS]: cel.bind(@r1, ["a"], cel.bind(@r0, [1], [@r0.exists(@it:0, @it:0 > 0)] + [@r0.exists(@it:1, @it:1 > 0)]) + [@r1.exists(@it:2, @it:2 == "a")] + [@r1.exists(@it:3, @it:3 == "a")]) == [true, true, true, true] [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[[1].exists(@it:0:0, @it:0:0 > 0)], [["a"].exists(@it:0:1, @it:0:1 == "a")]], @index0 + @index0 + @index1 + @index1 == [true, true, true, true]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), [@index0], ["a"].exists(@it:0:1, @it:0:1 == "a"), [@index2]], @index1 + @index1 + @index3 + @index3 == [true, true, true, true]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @it:0:0 > 0, @ac:0:0 || @index1, ["a"], @it:0:1 == "a", @ac:0:1 || @index4, [true, true, true, true]], [@index0.exists(@it:0:0, @index1)] + [@index0.exists(@it:0:0, @index1)] + [@index3.exists(@it:0:1, @index4)] + [@index3.exists(@it:0:1, @index4)] == @index6) [BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:0:0 || @it:0:0 > 0, @ac:0:1 || @it:0:1 == "a", [1], ["a"], [true, true, true, true]], [@index2.exists(@it:0:0, @it:0:0 > 0)] + [@index2.exists(@it:0:0, @it:0:0 > 0)] + [@index3.exists(@it:0:1, @it:0:1 == "a")] + [@index3.exists(@it:0:1, @it:0:1 == "a")] == @index4) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), ["a"].exists(@it:0:1, @it:0:1 == "a"), [@index0], [@index1], @index2 + @index2 + @index3 + @index3], @index4 == [true, true, true, true]) @@ -308,6 +327,7 @@ Source: [1].exists(i, i > 0) && [1].exists(j, j > 0) && [1].exists(k, k > 1) && Result: false [CASCADED_BINDS]: cel.bind(@r0, [1], @r0.exists(@it:0, @it:0 > 0) && @r0.exists(@it:1, @it:1 > 0) && @r0.exists(@it:2, @it:2 > 1) && [2].exists(@it:3, @it:3 > 1)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0)], @index0 && @index0 && [1].exists(@it:0:0, @it:0:0 > 1) && [2].exists(@it:0:0, @it:0:0 > 1)) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1], @it:0:0 > 0, @ac:0:0 || @index1, @it:0:0 > 1, @ac:0:0 || @index3, [2]], @index0.exists(@it:0:0, @index1) && @index0.exists(@it:0:0, @index1) && @index0.exists(@it:0:0, @index3) && @index5.exists(@it:0:0, @index3)) [BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:0:0 || @it:0:0 > 0, @ac:0:0 || @it:0:0 > 1, [1], [2]], @index2.exists(@it:0:0, @it:0:0 > 0) && @index2.exists(@it:0:0, @it:0:0 > 0) && @index2.exists(@it:0:0, @it:0:0 > 1) && @index3.exists(@it:0:0, @it:0:0 > 1)) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[1].exists(@it:0:0, @it:0:0 > 0), @ac:0:0 || @it:0:0 > 1, [1].exists(@it:0:0, @it:0:0 > 1), [2].exists(@it:0:0, @it:0:0 > 1)], @index0 && @index0 && @index2 && @index3) @@ -324,6 +344,7 @@ Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [[2, 3, 4], [2, 3, 4], [2, 3, Result: true [CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@it:1, @r0.map(@it:0, @it:0 + 1))) == cel.bind(@r1, [2, 3, 4], [@r1, @r1, @r1]) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1)) == [@index1, @index1, @index1]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1, 2, 3], [2, 3, 4]], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1)) == [@index1, @index1, @index1]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], [2, 3, 4], @it:1:0 + 1, [@index2], @ac:1:0 + @index3, [@index1, @index1, @index1]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index2)) == @index5) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[1, 2, 3], [2, 3, 4], [@it:1:0 + 1], @index0.map(@it:1:0, @it:1:0 + 1), @ac:0:0 + [@index3], @index0.map(@it:0:0, @index3)], @index5 == [@index1, @index1, @index1]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[1, 2, 3], [2, 3, 4], @ac:1:0 + [@it:1:0 + 1], [@index0.map(@it:1:0, @it:1:0 + 1)]], @index0.map(@it:0:0) == [@index1, @index1, @index1]) @@ -340,6 +361,7 @@ Source: [1, 2].map(y, [1, 2, 3].filter(x, x == y)) == [[1], [2]] Result: true [CASCADED_BINDS]: [1, 2].map(@it:1, [1, 2, 3].filter(@it:0, @it:0 == @it:1)) == [[1], [2]] [BLOCK_COMMON_SUBEXPR_ONLY]: [1, 2].map(@it:0:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)) == [[1], [2]] +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: [1, 2].map(@it:0:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)) == [[1], [2]] [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], [1, 2, 3], @it:1:0 == @it:0:0, [@it:1:0], @ac:1:0 + @index3, @index2 ? @index4 : @ac:1:0, [1], [2], [@index6, @index7]], @index0.map(@it:0:0, @index1.filter(@it:1:0, @index2)) == @index8) [BLOCK_RECURSION_DEPTH_2]: cel.@block([@ac:1:0 + [@it:1:0], (@it:1:0 == @it:0:0) ? @index0 : @ac:1:0, [1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0), @ac:0:0 + [@index2], [1, 2].map(@it:0:0, @index2), [[1], [2]]], @index4 == @index5) [BLOCK_RECURSION_DEPTH_3]: cel.@block([(@it:1:0 == @it:0:0) ? (@ac:1:0 + [@it:1:0]) : @ac:1:0, [[1, 2, 3].filter(@it:1:0, @it:1:0 == @it:0:0)]], [1, 2].map(@it:0:0) == [[1], [2]]) @@ -356,6 +378,7 @@ Source: [1,2,3].map(i, [1, 2, 3].map(i, i + 1)) == [1,2,3].map(j, [1, 2, 3].map( Result: true [CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], @r0.map(@it:1, @r0.map(@it:0, @it:0 + 1)) == @r0.map(@it:3, @r0.map(@it:2, @it:2 + 1))) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1))], @index1 == @index1) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1, 2, 3], @index0.map(@it:0:0, @index0.map(@it:1:0, @it:1:0 + 1))], @index1 == @index1) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], @it:1:0 + 1, [@index1], @ac:1:0 + @index2], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == @index0.map(@it:0:0, @index0.map(@it:1:0, @index1))) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[@it:1:0 + 1], [1, 2, 3].map(@it:1:0, @it:1:0 + 1), @ac:0:0 + [@index1], [1, 2, 3].map(@it:0:0, @index1)], @index3 == @index3) [BLOCK_RECURSION_DEPTH_3]: cel.@block([@ac:1:0 + [@it:1:0 + 1], [[1, 2, 3].map(@it:1:0, @it:1:0 + 1)], [1, 2, 3].map(@it:0:0)], @index2 == @index2) @@ -372,6 +395,7 @@ Source: 1 in [1,2,3] && 2 in [1,2,3] && 3 in [3, [1,2,3]] && 1 in [1,2,3] Result: true [CASCADED_BINDS]: cel.bind(@r0, [1, 2, 3], cel.bind(@r1, 1 in @r0, @r1 && 2 in @r0 && 3 in [3, @r0] && @r1)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2, 3], 1 in @index0], @index1 && 2 in @index0 && 3 in [3, @index0] && @index1) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1, 2, 3], 1 in @index0], @index1 && 2 in @index0 && 3 in [3, @index0] && @index1) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2, 3], 1 in @index0, 2 in @index0, @index1 && @index2, [3, @index0], 3 in @index4, @index5 && @index1], @index3 && @index6) [BLOCK_RECURSION_DEPTH_2]: cel.@block([1 in [1, 2, 3], [1, 2, 3], @index0 && 2 in @index1, 3 in [3, @index1]], @index2 && @index3 && @index0) [BLOCK_RECURSION_DEPTH_3]: cel.@block([1 in [1, 2, 3], [1, 2, 3], 3 in [3, @index1] && @index0], @index0 && 2 in @index1 && @index2) @@ -388,6 +412,7 @@ Source: 2 in {'a': 1, 2: {true: false}, 3: {true: false}} Result: true [CASCADED_BINDS]: 2 in cel.bind(@r0, {true: false}, {"a": 1, 2: @r0, 3: @r0}) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{true: false}], 2 in {"a": 1, 2: @index0, 3: @index0}) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{true: false}], 2 in {"a": 1, 2: @index0, 3: @index0}) [BLOCK_RECURSION_DEPTH_1]: cel.@block([{true: false}, {"a": 1, 2: @index0, 3: @index0}], 2 in @index1) [BLOCK_RECURSION_DEPTH_2]: cel.@block([{true: false}], 2 in {"a": 1, 2: @index0, 3: @index0}) [BLOCK_RECURSION_DEPTH_3]: cel.@block([{true: false}], 2 in {"a": 1, 2: @index0, 3: @index0}) @@ -404,6 +429,7 @@ Source: [1,2].map(i, [1, 2].map(i, [3,4])) == [[[3, 4], [3, 4]], [[3, 4], [3, 4] Result: true [CASCADED_BINDS]: cel.bind(@r1, [3, 4], cel.bind(@r0, [1, 2], @r0.map(@it:1, @r0.map(@it:0, @r1))) == cel.bind(@r2, [@r1, @r1], [@r2, @r2])) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([[1, 2], [3, 4], [@index1, @index1]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == [@index2, @index2]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([[1, 2], [3, 4], [@index1, @index1]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == [@index2, @index2]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([[1, 2], [3, 4], [@index1, @index1], [@index1], @ac:1:0 + @index3, [@index2, @index2]], @index0.map(@it:0:0, @index0.map(@it:1:0, @index1)) == @index5) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[[3, 4], [3, 4]], [1, 2], [[3, 4]], @index1.map(@it:1:0, [3, 4]), @ac:0:0 + [@index3], @index1.map(@it:0:0, @index3)], @index5 == [@index0, @index0]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[[3, 4], [3, 4]], [1, 2], @ac:1:0 + [[3, 4]], [@index1.map(@it:1:0, [3, 4])]], @index1.map(@it:0:0) == [@index0, @index0]) @@ -420,6 +446,7 @@ Source: [x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3 Result: true [CASCADED_BINDS]: cel.bind(@r0, x - 1, cel.bind(@r1, @r0 > 3, [@r1 ? @r0 : 5].exists(@it:0, @it:0 - 1 > 3) || @r1)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index1) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([x - 1, @index0 > 3], [@index1 ? @index0 : 5].exists(@it:0:0, @it:0:0 - 1 > 3) || @index1) [BLOCK_RECURSION_DEPTH_1]: cel.@block([x - 1, @index0 > 3, @index1 ? @index0 : 5, [@index2], @it:0:0 - 1, @index4 > 3, @ac:0:0 || @index5], @index3.exists(@it:0:0, @index5) || @index1) [BLOCK_RECURSION_DEPTH_2]: cel.@block([x - 1 > 3, @index0 ? (x - 1) : 5, @it:0:0 - 1 > 3, [@index1], @ac:0:0 || @index2], @index3.exists(@it:0:0, @index2) || @index0) [BLOCK_RECURSION_DEPTH_3]: cel.@block([x - 1 > 3, [@index0 ? (x - 1) : 5], @ac:0:0 || @it:0:0 - 1 > 3, @index1.exists(@it:0:0, @it:0:0 - 1 > 3)], @index3 || @index0) @@ -436,6 +463,7 @@ Source: ["foo", "bar"].map(x, [x + x, x + x]).map(x, [x + x, x + x]) Result: [[[foofoo, foofoo, foofoo, foofoo], [foofoo, foofoo, foofoo, foofoo]], [[barbar, barbar, barbar, barbar], [barbar, barbar, barbar, barbar]]] [CASCADED_BINDS]: ["foo", "bar"].map(@it:0, cel.bind(@r0, @it:0 + @it:0, [@r0, @r0])).map(@it:1, cel.bind(@r1, @it:1 + @it:1, [@r1, @r1])) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: ["foo", "bar"].map(@it:1:0, [@it:1:0 + @it:1:0, @it:1:0 + @it:1:0]).map(@it:0:0, [@it:0:0 + @it:0:0, @it:0:0 + @it:0:0]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, ["foo", "bar"], [@index0, @index0], [@index3], @ac:1:0 + @index4, [@index1, @index1], [@index6], @ac:0:0 + @index7], @index2.map(@it:1:0, @index3).map(@it:0:0, @index6)) [BLOCK_RECURSION_DEPTH_2]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, [[@index0, @index0]], ["foo", "bar"].map(@it:1:0, [@index0, @index0]), [[@index1, @index1]]], @index3.map(@it:0:0, [@index1, @index1])) [BLOCK_RECURSION_DEPTH_3]: cel.@block([@it:1:0 + @it:1:0, @it:0:0 + @it:0:0, @ac:1:0 + [[@index0, @index0]], @ac:0:0 + [[@index1, @index1]]], ["foo", "bar"].map(@it:1:0, [@index0, @index0]).map(@it:0:0, [@index1, @index1])) @@ -452,6 +480,7 @@ Source: has({'a': true}.a) && {'a':true}['a'] Result: true [CASCADED_BINDS]: cel.bind(@r0, {"a": true}, has(@r0.a) && @r0["a"]) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{"a": true}], has(@index0.a) && @index0["a"]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{"a": true}], has(@index0.a) && @index0["a"]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([{"a": true}, has(@index0.a), @index0["a"]], @index1 && @index2) [BLOCK_RECURSION_DEPTH_2]: cel.@block([{"a": true}], has(@index0.a) && @index0["a"]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([{"a": true}], has(@index0.a) && @index0["a"]) @@ -468,6 +497,7 @@ Source: has({'a': true}.a) && has({'a': true}.a) Result: true [CASCADED_BINDS]: cel.bind(@r0, has({"a": true}.a), @r0 && @r0) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([has({"a": true}.a)], @index0 && @index0) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([has({"a": true}.a)], @index0 && @index0) [BLOCK_RECURSION_DEPTH_1]: cel.@block([{"a": true}, has(@index0.a)], @index1 && @index1) [BLOCK_RECURSION_DEPTH_2]: cel.@block([has({"a": true}.a)], @index0 && @index0) [BLOCK_RECURSION_DEPTH_3]: cel.@block([has({"a": true}.a)], @index0 && @index0) @@ -484,6 +514,7 @@ Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type, has(@r0.payload) ? @r0.payload.single_int64 : 0) == 10 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type], (has(@index0.payload) ? @index0.payload.single_int64 : 0) == 10) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type], (has(@index0.payload) ? @index0.payload.single_int64 : 0) == 10) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, has(@index0.payload), @index0.payload, @index2.single_int64, @index1 ? @index3 : 0], @index4 == 10) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type, @index0.payload.single_int64, has(@index0.payload) ? @index1 : 0], @index2 == 10) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type, has(@index0.payload) ? @index0.payload.single_int64 : 0], @index1 == 10) @@ -500,6 +531,7 @@ Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : msg Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type, cel.bind(@r1, @r0.payload.single_int64, has(@r0.payload) ? @r1 : (@r1 * 0))) == 10 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type, @index0.payload.single_int64], (has(@index0.payload) ? @index1 : (@index1 * 0)) == 10) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type, @index0.payload.single_int64], (has(@index0.payload) ? @index1 : (@index1 * 0)) == 10) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, has(@index0.payload), @index2 * 0, @index3 ? @index2 : @index4], @index5 == 10) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64, has(msg.oneof_type.payload), @index2 ? @index1 : (@index1 * 0)], @index3 == 10) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, has(msg.oneof_type.payload) ? @index0 : (@index0 * 0)], @index1 == 10) @@ -516,6 +548,7 @@ Source: (has(msg.oneof_type.payload.single_int64) ? msg.oneof_type.payload.singl Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, has(@r0.single_int64) ? @r1 : (@r1 * 0))) == 10 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], (has(@index0.single_int64) ? @index1 : (@index1 * 0)) == 10) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, @index0.single_int64], (has(@index0.single_int64) ? @index1 : (@index1 * 0)) == 10) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, has(@index1.single_int64), @index2 * 0, @index3 ? @index2 : @index4], @index5 == 10) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64, has(@index0.single_int64) ? @index1 : (@index1 * 0)], @index2 == 10) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, has(msg.oneof_type.payload.single_int64)], (@index1 ? @index0 : (@index0 * 0)) == 10) @@ -532,6 +565,7 @@ Source: (has(msg.oneof_type) && has(msg.oneof_type.payload) && has(msg.oneof_typ Result: true [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type, cel.bind(@r1, @r0.payload, (has(msg.oneof_type) && has(@r0.payload) && has(@r1.single_int64)) ? cel.bind(@r2, @r1.map_string_string, (has(@r1.map_string_string) && has(@r2.key)) ? (@r2.key == "A") : false) : false)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_string_string], (has(msg.oneof_type) && has(@index0.payload) && has(@index1.single_int64)) ? ((has(@index1.map_string_string) && has(@index2.key)) ? (@index2.key == "A") : false) : false) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_string_string], (has(msg.oneof_type) && has(@index0.payload) && has(@index1.single_int64)) ? ((has(@index1.map_string_string) && has(@index2.key)) ? (@index2.key == "A") : false) : false) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.map_string_string, has(msg.oneof_type), has(@index0.payload), @index3 && @index4, has(@index1.single_int64), @index5 && @index6, has(@index1.map_string_string), has(@index2.key), @index8 && @index9, @index2.key, @index11 == "A", @index10 ? @index12 : false], @index7 ? @index13 : false) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.map_string_string, has(msg.oneof_type.payload), has(msg.oneof_type) && @index2, @index3 && has(@index0.single_int64), has(@index0.map_string_string) && has(@index1.key), @index1.key == "A"], @index4 ? (@index5 ? @index6 : false) : false) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.map_string_string, msg.oneof_type.payload, has(msg.oneof_type) && has(msg.oneof_type.payload), (has(@index1.map_string_string) && has(@index0.key)) ? (@index0.key == "A") : false], (@index2 && has(@index1.single_int64)) ? @index3 : false) @@ -548,6 +582,7 @@ Source: [10, ?optional.none(), [?optional.none(), ?opt_x], [?optional.none(), ?o Result: true [CASCADED_BINDS]: cel.bind(@r0, optional.none(), cel.bind(@r1, [?@r0, ?opt_x], [10, ?@r0, @r1, @r1])) == cel.bind(@r2, [5], [10, @r2, @r2]) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([optional.none(), [?@index0, ?opt_x], [5]], [10, ?@index0, @index1, @index1] == [10, @index2, @index2]) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([optional.none(), [?@index0, ?opt_x], [5]], [10, ?@index0, @index1, @index1] == [10, @index2, @index2]) [BLOCK_RECURSION_DEPTH_1]: cel.@block([optional.none(), [?@index0, ?opt_x], [5], [10, ?@index0, @index1, @index1], [10, @index2, @index2]], @index3 == @index4) [BLOCK_RECURSION_DEPTH_2]: cel.@block([[?optional.none(), ?opt_x], [5], [10, ?optional.none(), @index0, @index0]], @index2 == [10, @index1, @index1]) [BLOCK_RECURSION_DEPTH_3]: cel.@block([[?optional.none(), ?opt_x], [5]], [10, ?optional.none(), @index0, @index0] == [10, @index1, @index1]) @@ -564,6 +599,7 @@ Source: {?'hello': optional.of('hello')}['hello'] + {?'hello': optional.of('hell Result: true [CASCADED_BINDS]: cel.bind(@r0, {?"hello": optional.of("hello")}["hello"], @r0 + @r0) == "hellohello" [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{?"hello": optional.of("hello")}["hello"]], @index0 + @index0 == "hellohello") +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{?"hello": optional.of("hello")}["hello"]], @index0 + @index0 == "hellohello") [BLOCK_RECURSION_DEPTH_1]: cel.@block([optional.of("hello"), {?"hello": @index0}, @index1["hello"], @index2 + @index2], @index3 == "hellohello") [BLOCK_RECURSION_DEPTH_2]: cel.@block([{?"hello": optional.of("hello")}, @index0["hello"]], @index1 + @index1 == "hellohello") [BLOCK_RECURSION_DEPTH_3]: cel.@block([{?"hello": optional.of("hello")}["hello"]], @index0 + @index0 == "hellohello") @@ -580,6 +616,7 @@ Source: {?'key': optional.of('test')}[?'bogus'].or({'key': 'test'}[?'bogus']).or Result: true [CASCADED_BINDS]: cel.bind(@r0, {"key": "test"}, {?"key": optional.of("test")}[?"bogus"].or(@r0[?"bogus"]).orValue(@r0["key"])) == "test" [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{"key": "test"}], {?"key": optional.of("test")}[?"bogus"].or(@index0[?"bogus"]).orValue(@index0["key"]) == "test") +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([{"key": "test"}], {?"key": optional.of("test")}[?"bogus"].or(@index0[?"bogus"]).orValue(@index0["key"]) == "test") [BLOCK_RECURSION_DEPTH_1]: cel.@block([{"key": "test"}, optional.of("test"), {?"key": @index1}, @index2[?"bogus"], @index0[?"bogus"], @index3.or(@index4), @index0["key"], @index5.orValue(@index6)], @index7 == "test") [BLOCK_RECURSION_DEPTH_2]: cel.@block([{"key": "test"}, {?"key": optional.of("test")}, @index1[?"bogus"].or(@index0[?"bogus"]), @index2.orValue(@index0["key"])], @index3 == "test") [BLOCK_RECURSION_DEPTH_3]: cel.@block([{"key": "test"}, {?"key": optional.of("test")}[?"bogus"], @index1.or(@index0[?"bogus"]).orValue(@index0["key"])], @index2 == "test") @@ -596,6 +633,7 @@ Source: TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: o Result: true [CASCADED_BINDS]: cel.bind(@r0, TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}, @r0.single_int32 + @r0.single_int64) == 5 [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}], @index0.single_int32 + @index0.single_int64 == 5) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}], @index0.single_int32 + @index0.single_int64 == 5) [BLOCK_RECURSION_DEPTH_1]: cel.@block([optional.ofNonZeroValue(1), optional.of(4), TestAllTypes{?single_int64: @index0, ?single_int32: @index1}, @index2.single_int32, @index2.single_int64, @index3 + @index4], @index5 == 5) [BLOCK_RECURSION_DEPTH_2]: cel.@block([TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}, @index0.single_int32 + @index0.single_int64], @index1 == 5) [BLOCK_RECURSION_DEPTH_3]: cel.@block([TestAllTypes{?single_int64: optional.ofNonZeroValue(1), ?single_int32: optional.of(4)}], @index0.single_int32 + @index0.single_int64 == 5) @@ -612,6 +650,7 @@ Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('h' + 'e' + 'l' + 'l' + Result: true [CASCADED_BINDS]: cel.bind(@r0, "h" + "e" + "l" + "l" + "o", (@r0 + " world").matches(@r0)) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block(["h" + "e" + "l" + "l" + "o"], (@index0 + " world").matches(@index0)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block(["h" + "e" + "l" + "l" + "o"], (@index0 + " world").matches(@index0)) [BLOCK_RECURSION_DEPTH_1]: cel.@block(["h" + "e", @index0 + "l", @index1 + "l", @index2 + "o", @index3 + " world"], @index4.matches(@index3)) [BLOCK_RECURSION_DEPTH_2]: cel.@block(["h" + "e" + "l", @index0 + "l" + "o"], (@index1 + " world").matches(@index1)) [BLOCK_RECURSION_DEPTH_3]: cel.@block(["h" + "e" + "l" + "l", @index0 + "o"], (@index1 + " world").matches(@index1)) @@ -628,6 +667,7 @@ Source: 'hello world'.matches('h' + 'e' + 'l' + 'l' + 'o') Result: true [CASCADED_BINDS]: "hello world".matches("h" + "e" + "l" + "l" + "o") [BLOCK_COMMON_SUBEXPR_ONLY]: "hello world".matches("h" + "e" + "l" + "l" + "o") +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: "hello world".matches("h" + "e" + "l" + "l" + "o") [BLOCK_RECURSION_DEPTH_1]: cel.@block(["h" + "e", @index0 + "l", @index1 + "l", @index2 + "o"], "hello world".matches(@index3)) [BLOCK_RECURSION_DEPTH_2]: cel.@block(["h" + "e" + "l", @index0 + "l" + "o"], "hello world".matches(@index1)) [BLOCK_RECURSION_DEPTH_3]: cel.@block(["h" + "e" + "l" + "l"], "hello world".matches(@index0 + "o")) @@ -644,6 +684,7 @@ Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('hello') Result: true [CASCADED_BINDS]: ("h" + "e" + "l" + "l" + "o" + " world").matches("hello") [BLOCK_COMMON_SUBEXPR_ONLY]: ("h" + "e" + "l" + "l" + "o" + " world").matches("hello") +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: ("h" + "e" + "l" + "l" + "o" + " world").matches("hello") [BLOCK_RECURSION_DEPTH_1]: cel.@block(["h" + "e", @index0 + "l", @index1 + "l", @index2 + "o", @index3 + " world"], @index4.matches("hello")) [BLOCK_RECURSION_DEPTH_2]: cel.@block(["h" + "e" + "l", @index0 + "l" + "o"], (@index1 + " world").matches("hello")) [BLOCK_RECURSION_DEPTH_3]: cel.@block(["h" + "e" + "l" + "l"], (@index0 + "o" + " world").matches("hello")) @@ -660,6 +701,7 @@ Source: ('h' + 'e' + 'l' + 'l' + 'o' + ' world').matches('w' + 'o' + 'r' + 'l' + Result: true [CASCADED_BINDS]: ("h" + "e" + "l" + "l" + "o" + " world").matches("w" + "o" + "r" + "l" + "d") [BLOCK_COMMON_SUBEXPR_ONLY]: ("h" + "e" + "l" + "l" + "o" + " world").matches("w" + "o" + "r" + "l" + "d") +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: ("h" + "e" + "l" + "l" + "o" + " world").matches("w" + "o" + "r" + "l" + "d") [BLOCK_RECURSION_DEPTH_1]: cel.@block(["h" + "e", @index0 + "l", @index1 + "l", @index2 + "o", @index3 + " world", "w" + "o", @index5 + "r", @index6 + "l", @index7 + "d"], @index4.matches(@index8)) [BLOCK_RECURSION_DEPTH_2]: cel.@block(["h" + "e" + "l", @index0 + "l" + "o", "w" + "o" + "r", @index2 + "l" + "d"], (@index1 + " world").matches(@index3)) [BLOCK_RECURSION_DEPTH_3]: cel.@block(["h" + "e" + "l" + "l", "w" + "o" + "r" + "l"], (@index0 + "o" + " world").matches(@index1 + "d")) @@ -676,6 +718,7 @@ Source: non_pure_custom_func(msg.oneof_type.payload.single_int64) + non_pure_cus Result: 31 [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, @r0.single_int64, non_pure_custom_func(@r1) + non_pure_custom_func(@r0.single_int32) + non_pure_custom_func(@r1))) + non_pure_custom_func(msg.single_int64) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64], non_pure_custom_func(@index2) + non_pure_custom_func(@index1.single_int32) + non_pure_custom_func(@index2) + non_pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, @index0.single_int64], non_pure_custom_func(@index1) + non_pure_custom_func(@index0.single_int32) + non_pure_custom_func(@index1) + non_pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64], non_pure_custom_func(@index0) + non_pure_custom_func(msg.oneof_type.payload.single_int32) + non_pure_custom_func(@index0) + non_pure_custom_func(msg.single_int64)) @@ -692,6 +735,7 @@ Source: pure_custom_func(msg.oneof_type.payload.single_int64) + pure_custom_func Result: 31 [CASCADED_BINDS]: cel.bind(@r0, msg.oneof_type.payload, cel.bind(@r1, pure_custom_func(@r0.single_int64), @r1 + pure_custom_func(@r0.single_int32) + @r1)) + pure_custom_func(msg.single_int64) [BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) +[BLOCK_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64)], @index1 + pure_custom_func(@index0.single_int32) + @index1 + pure_custom_func(msg.single_int64)) [BLOCK_RECURSION_DEPTH_1]: cel.@block([msg.oneof_type, @index0.payload, @index1.single_int64, pure_custom_func(@index2), @index1.single_int32, pure_custom_func(@index4), @index3 + @index5, @index6 + @index3, msg.single_int64, pure_custom_func(@index8)], @index7 + @index9) [BLOCK_RECURSION_DEPTH_2]: cel.@block([msg.oneof_type.payload, pure_custom_func(@index0.single_int64), pure_custom_func(@index0.single_int32), @index1 + @index2 + @index1, pure_custom_func(msg.single_int64)], @index3 + @index4) [BLOCK_RECURSION_DEPTH_3]: cel.@block([msg.oneof_type.payload.single_int64, pure_custom_func(@index0), msg.oneof_type.payload.single_int32, @index1 + pure_custom_func(@index2) + @index1], @index3 + pure_custom_func(msg.single_int64)) From 502830e4535c45195470121c0eb94db4844a0697 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Wed, 21 Aug 2024 13:05:26 -0700 Subject: [PATCH 26/33] Migrate test_all_types proto over to the cel-spec variant No functional changes. This is just a test-cleanup to remove the divergent test_all_types proto. PiperOrigin-RevId: 665999916 --- WORKSPACE | 6 +- .../src/test/java/dev/cel/bundle/BUILD.bazel | 6 +- .../test/java/dev/cel/bundle/CelImplTest.java | 16 +- .../src/test/java/dev/cel/checker/BUILD.bazel | 6 +- .../cel/checker/CelCheckerLegacyImplTest.java | 6 +- .../cel/checker/CelProtoExprVisitorTest.java | 2 +- .../checker/DescriptorTypeProviderTest.java | 35 ++--- .../java/dev/cel/checker/ExprCheckerTest.java | 86 +++++------ .../checker/TypeProviderLegacyImplTest.java | 34 ++--- .../test/resources/aggregateMessage.baseline | 2 +- .../src/test/resources/anyMessage.baseline | 6 +- .../src/test/resources/dynOperators.baseline | 6 +- .../resources/dynOperatorsAtRuntime.baseline | 6 +- .../src/test/resources/enumValues.baseline | 2 +- .../src/test/resources/equalsWrapper.baseline | 14 +- .../test/resources/globalEnumValues.baseline | 2 +- .../resources/jsonStructTypeError.baseline | 2 +- .../test/resources/listElemTypeError.baseline | 4 +- .../resources/listIndexTypeError.baseline | 4 +- .../src/test/resources/listOperators.baseline | 18 +-- .../resources/listRepeatedOperators.baseline | 6 +- checker/src/test/resources/mapEmpty.baseline | 4 +- checker/src/test/resources/mapExpr.baseline | 8 +- .../src/test/resources/mapFilterExpr.baseline | 8 +- .../test/resources/mapIndexTypeError.baseline | 4 +- .../src/test/resources/mapOperators.baseline | 12 +- .../resources/messageFieldSelect.baseline | 12 +- .../messageFieldSelectError.baseline | 2 +- .../resources/namespacedVariables.baseline | 6 +- .../src/test/resources/nestedEnums.baseline | 16 +- .../test/resources/nullableMessage.baseline | 10 +- .../resources/nullablePrimitiveError.baseline | 2 +- .../test/resources/nullableWrapper.baseline | 4 +- .../resources/operatorsConditional.baseline | 4 +- checker/src/test/resources/optionals.baseline | 2 +- .../resources/proto2PrimitiveField.baseline | 10 +- .../src/test/resources/quantifiers.baseline | 8 +- .../test/resources/quantifiersErrors.baseline | 4 +- .../resources/referenceTypeAbsolute.baseline | 4 +- .../resources/referenceTypeRelative.baseline | 2 +- .../test/resources/referenceValue.baseline | 4 +- .../userFunctionAddsOverload.baseline | 6 +- checker/src/test/resources/wrapper.baseline | 4 +- common/resources/testdata/proto2/BUILD.bazel | 20 --- common/resources/testdata/proto3/BUILD.bazel | 5 - .../resources/testdata/proto2/BUILD.bazel | 59 -------- .../proto2/messages_extensions_proto2.proto | 49 ------- .../testdata/proto2/messages_proto2.proto | 44 ------ .../testdata/proto2/test_all_types.proto | 134 ----------------- .../resources/testdata/proto3/BUILD.bazel | 21 --- .../testdata/proto3/test_all_types.proto | 138 ------------------ .../test/java/dev/cel/common/ast/BUILD.bazel | 2 +- .../cel/common/ast/CelExprFormatterTest.java | 6 +- .../cel/common/ast/CelExprVisitorTest.java | 2 +- .../java/dev/cel/common/internal/BUILD.bazel | 6 +- .../internal/CombinedDescriptorPoolTest.java | 13 +- .../DefaultInstanceMessageFactoryTest.java | 2 +- .../internal/DefaultMessageFactoryTest.java | 4 +- .../common/internal/ProtoEqualityTest.java | 6 +- .../dev/cel/common/navigation/BUILD.bazel | 2 +- .../CelNavigableExprVisitorTest.java | 12 +- .../java/dev/cel/common/types/BUILD.bazel | 5 +- .../types/ProtoMessageTypeProviderTest.java | 93 ++++++------ .../java/dev/cel/common/values/BUILD.bazel | 4 +- .../values/ProtoMessageValueProviderTest.java | 16 +- .../common/values/ProtoMessageValueTest.java | 29 ++-- .../test/java/dev/cel/extensions/BUILD.bazel | 6 +- .../extensions/CelBindingsExtensionsTest.java | 2 +- .../extensions/CelOptionalLibraryTest.java | 6 +- .../extensions/CelProtoExtensionsTest.java | 124 ++++++++-------- .../cel/extensions/CelSetsExtensionsTest.java | 4 +- .../dev/cel/optimizer/AstMutatorTest.java | 4 +- .../test/java/dev/cel/optimizer/BUILD.bazel | 2 +- .../dev/cel/optimizer/optimizers/BUILD.bazel | 2 +- .../ConstantFoldingOptimizerTest.java | 4 +- .../SubexpressionOptimizerBaselineTest.java | 6 +- .../SubexpressionOptimizerTest.java | 2 +- .../src/test/java/dev/cel/policy/BUILD.bazel | 2 +- .../cel/policy/CelPolicyCompilerImplTest.java | 2 +- policy/src/test/resources/pb/config.yaml | 4 +- .../java/dev/cel/runtime/ActivationTest.java | 6 +- .../src/test/java/dev/cel/runtime/BUILD.bazel | 5 +- .../cel/runtime/CelRuntimeLegacyImplTest.java | 4 +- .../java/dev/cel/runtime/CelRuntimeTest.java | 6 +- .../DescriptorMessageProviderTest.java | 23 +-- .../dev/cel/runtime/MessageFactoryTest.java | 2 +- .../java/dev/cel/runtime/async/BUILD.bazel | 2 +- .../async/CelAsyncRuntimeImplTest.java | 2 +- .../resources/dynamicMessage_adapted.baseline | 92 ++++++------ .../dynamicMessage_dynamicDescriptor.baseline | 28 ++-- .../resources/extensionManipulation.baseline | 44 +++--- .../test/resources/fieldManipulation.baseline | 60 ++++---- runtime/src/test/resources/has.baseline | 4 +- .../test/resources/jsonValueTypes.baseline | 18 +-- runtime/src/test/resources/lists.baseline | 18 +-- runtime/src/test/resources/maps.baseline | 22 +-- runtime/src/test/resources/messages.baseline | 10 +- .../resources/namespacedVariables.baseline | 2 +- .../src/test/resources/nestedEnums.baseline | 6 +- .../src/test/resources/packUnpackAny.baseline | 28 ++-- .../test/resources/typeComparisons.baseline | 2 +- .../src/test/resources/unknownField.baseline | 14 +- .../test/resources/unknownResultSet.baseline | 82 +++++------ runtime/src/test/resources/wrappers.baseline | 6 +- .../src/main/java/dev/cel/testing/BUILD.bazel | 2 +- .../dev/cel/testing/BaseInterpreterTest.java | 24 +-- 106 files changed, 627 insertions(+), 1132 deletions(-) delete mode 100644 common/resources/testdata/proto2/BUILD.bazel delete mode 100644 common/src/main/resources/testdata/proto2/BUILD.bazel delete mode 100644 common/src/main/resources/testdata/proto2/messages_extensions_proto2.proto delete mode 100644 common/src/main/resources/testdata/proto2/messages_proto2.proto delete mode 100644 common/src/main/resources/testdata/proto2/test_all_types.proto delete mode 100644 common/src/main/resources/testdata/proto3/test_all_types.proto diff --git a/WORKSPACE b/WORKSPACE index 9ba1c3f0c..37c7cd2de 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -149,10 +149,10 @@ http_archive( # cel-spec api/expr canonical protos http_archive( name = "cel_spec", - sha256 = "b4efed0586004c538fe2be4f0472a1e2483790895493502fcab58f56060f6d37", - strip_prefix = "cel-spec-0.16.0", + sha256 = "7136e18be8881153e05229fc040f8790b634af833d28efb102da00bad640b3ea", + strip_prefix = "cel-spec-e363cad95c4da033336f1350de063b16a3e36cd2", urls = [ - "https://github.com/google/cel-spec/archive/refs/tags/v0.16.0.tar.gz", + "https://github.com/google/cel-spec/archive/e363cad95c4da033336f1350de063b16a3e36cd2.tar.gz", ], ) diff --git a/bundle/src/test/java/dev/cel/bundle/BUILD.bazel b/bundle/src/test/java/dev/cel/bundle/BUILD.bazel index f19406eec..3ca1dd570 100644 --- a/bundle/src/test/java/dev/cel/bundle/BUILD.bazel +++ b/bundle/src/test/java/dev/cel/bundle/BUILD.bazel @@ -20,11 +20,7 @@ java_library( "//common:options", "//common:proto_ast", "//common/ast", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto2:test_all_types_java_proto", "//common/resources/testdata/proto3:standalone_global_enum_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/testing", "//common/types", "//common/types:cel_types", @@ -38,6 +34,8 @@ java_library( "//runtime:unknown_attributes", "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@com_google_googleapis//google/type:type_java_proto", "@maven//:com_google_guava_guava", diff --git a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java index ecbac380e..db8f311e9 100644 --- a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java +++ b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java @@ -35,6 +35,8 @@ import dev.cel.expr.Reference; import dev.cel.expr.Type; import dev.cel.expr.Type.PrimitiveType; +import com.google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -98,7 +100,6 @@ import dev.cel.runtime.CelVariableResolver; import dev.cel.runtime.UnknownContext; import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -1021,7 +1022,7 @@ public void program_enumTypeTransitiveResolution() throws Exception { Cel cel = standardCelBuilderWithMacros() .setOptions(CelOptions.current().resolveTypeDependencies(true).build()) - .addMessageTypes(TestAllTypes.getDescriptor()) + .addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor()) .setResultType(StructTypeReference.create("google.protobuf.NullValue")) .setContainer("google.protobuf") .build(); @@ -1030,7 +1031,6 @@ public void program_enumTypeTransitiveResolution() throws Exception { // enum within this 'Value' struct. // As deep type dependency is enabled, the following evaluation should work by as the // 'NullValue' enum type is transitively discovered - CelRuntime.Program program = cel.createProgram(cel.compile("Value{null_value: NullValue.NULL_VALUE}").getAst()); assertThat(program.eval()).isEqualTo(NullValue.NULL_VALUE); @@ -1055,7 +1055,7 @@ public void compile_enumTypeTransitiveResolutionFailure() { Cel cel = standardCelBuilderWithMacros() .setOptions(CelOptions.current().resolveTypeDependencies(false).build()) - .addMessageTypes(TestAllTypes.getDescriptor()) + .addMessageTypes(Proto2ExtensionScopedMessage.getDescriptor()) .setResultType(StructTypeReference.create("google.protobuf.NullValue")) .setContainer("google.protobuf") .build(); @@ -1817,13 +1817,13 @@ public void programAdvanceEvaluation_partialUnknownMessageFieldPropagates() thro .addMessageTypes(TestAllTypes.getDescriptor()) .addVar( "partialMessage1", - StructTypeReference.create("dev.cel.testing.testdata.proto3.TestAllTypes")) + StructTypeReference.create("google.api.expr.test.v1.proto3.TestAllTypes")) .addVar( "partialMessage2", - StructTypeReference.create("dev.cel.testing.testdata.proto3.TestAllTypes")) + StructTypeReference.create("google.api.expr.test.v1.proto3.TestAllTypes")) .setResultType( - StructTypeReference.create("dev.cel.testing.testdata.proto3.NestedTestAllTypes")) - .setContainer("dev.cel.testing.testdata.proto3") + StructTypeReference.create("google.api.expr.test.v1.proto3.NestedTestAllTypes")) + .setContainer("google.api.expr.test.v1.proto3") .addFunctionBindings() .build(); Program program = diff --git a/checker/src/test/java/dev/cel/checker/BUILD.bazel b/checker/src/test/java/dev/cel/checker/BUILD.bazel index 52a39a8ae..ff4b87a34 100644 --- a/checker/src/test/java/dev/cel/checker/BUILD.bazel +++ b/checker/src/test/java/dev/cel/checker/BUILD.bazel @@ -27,11 +27,7 @@ java_library( "//common/ast", "//common/internal:env_visitor", "//common/internal:errors", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto2:test_all_types_java_proto", "//common/resources/testdata/proto3:standalone_global_enum_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//common/types:cel_types", "//common/types:json", @@ -49,6 +45,8 @@ java_library( "//:java_truth", "@maven//:com_google_truth_extensions_truth_proto_extension", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", ], diff --git a/checker/src/test/java/dev/cel/checker/CelCheckerLegacyImplTest.java b/checker/src/test/java/dev/cel/checker/CelCheckerLegacyImplTest.java index 1f96367f3..4e0c15576 100644 --- a/checker/src/test/java/dev/cel/checker/CelCheckerLegacyImplTest.java +++ b/checker/src/test/java/dev/cel/checker/CelCheckerLegacyImplTest.java @@ -16,12 +16,12 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOverloadDecl; import dev.cel.common.CelVarDecl; import dev.cel.common.types.SimpleType; import dev.cel.compiler.CelCompilerFactory; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -63,7 +63,7 @@ public void toCheckerBuilder_collectionProperties_copied() { .addMessageTypes(TestAllTypes.getDescriptor()) .addFileTypes(TestAllTypes.getDescriptor().getFile()) .addProtoTypeMasks( - ProtoTypeMask.ofAllFields("dev.cel.testing.testdata.proto2.TestAllTypes")) + ProtoTypeMask.ofAllFields("google.api.expr.test.v1.proto3.TestAllTypes")) .addLibraries(new CelCheckerLibrary() {}); CelCheckerLegacyImpl celChecker = (CelCheckerLegacyImpl) celCheckerBuilder.build(); @@ -93,7 +93,7 @@ public void toCheckerBuilder_collectionProperties_areImmutable() { celCheckerBuilder.addMessageTypes(TestAllTypes.getDescriptor()); celCheckerBuilder.addFileTypes(TestAllTypes.getDescriptor().getFile()); celCheckerBuilder.addProtoTypeMasks( - ProtoTypeMask.ofAllFields("dev.cel.testing.testdata.proto2.TestAllTypes")); + ProtoTypeMask.ofAllFields("google.api.expr.test.v1.proto3.TestAllTypes")); celCheckerBuilder.addLibraries(new CelCheckerLibrary() {}); assertThat(newCheckerBuilder.getFunctionDecls().build()).isEmpty(); diff --git a/checker/src/test/java/dev/cel/checker/CelProtoExprVisitorTest.java b/checker/src/test/java/dev/cel/checker/CelProtoExprVisitorTest.java index 54972b931..3b598d4c7 100644 --- a/checker/src/test/java/dev/cel/checker/CelProtoExprVisitorTest.java +++ b/checker/src/test/java/dev/cel/checker/CelProtoExprVisitorTest.java @@ -19,6 +19,7 @@ import dev.cel.expr.Constant; import dev.cel.expr.Expr; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.auto.value.AutoValue; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.types.SimpleType; @@ -26,7 +27,6 @@ import dev.cel.compiler.CelCompilerFactory; import dev.cel.parser.CelStandardMacro; import dev.cel.parser.Operator; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Before; import org.junit.Test; diff --git a/checker/src/test/java/dev/cel/checker/DescriptorTypeProviderTest.java b/checker/src/test/java/dev/cel/checker/DescriptorTypeProviderTest.java index d7fc84202..46e3a419d 100644 --- a/checker/src/test/java/dev/cel/checker/DescriptorTypeProviderTest.java +++ b/checker/src/test/java/dev/cel/checker/DescriptorTypeProviderTest.java @@ -17,13 +17,13 @@ import static com.google.common.truth.Truth.assertThat; import dev.cel.expr.Type; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.rpc.context.AttributeContext; import dev.cel.checker.TypeProvider.CombinedTypeProvider; import dev.cel.checker.TypeProvider.ExtensionFieldType; import dev.cel.common.types.CelTypes; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto2.Proto2Message; import java.util.Arrays; import org.junit.Assert; import org.junit.Test; @@ -50,23 +50,14 @@ public void lookupFieldNames_undeclaredMessageType() { @Test public void lookupFieldNames_groupTypeField() throws Exception { - Type proto2MessageType = - CelTypes.createMessage("dev.cel.testing.testdata.proto2.Proto2Message"); + Type proto2MessageType = CelTypes.createMessage("google.api.expr.test.v1.proto2.TestAllTypes"); TypeProvider typeProvider = new DescriptorTypeProvider( ImmutableList.of( - Proto2Message.getDescriptor().getFile(), MessagesProto2Extensions.getDescriptor())); - assertThat(typeProvider.lookupFieldNames(proto2MessageType)) - .containsExactly( - "single_nested_test_all_types", - "single_enum", - "nestedgroup", - "single_int32", - "single_fixed32", - "single_fixed64"); + TestAllTypes.getDescriptor().getFile(), TestAllTypesExtensions.getDescriptor())); assertThat(typeProvider.lookupFieldType(proto2MessageType, "nestedgroup").type()) .isEqualTo( - CelTypes.createMessage("dev.cel.testing.testdata.proto2.Proto2Message.NestedGroup")); + CelTypes.createMessage("google.api.expr.test.v1.proto2.TestAllTypes.NestedGroup")); } @Test @@ -103,43 +94,41 @@ public void lookupExtensionType_combinedProvider() { final TypeProvider configuredProvider = new DescriptorTypeProvider( ImmutableList.of( - Proto2Message.getDescriptor().getFile(), MessagesProto2Extensions.getDescriptor())); + TestAllTypes.getDescriptor().getFile(), TestAllTypesExtensions.getDescriptor())); final TypeProvider partialProvider = // The partial provider has no extension lookup. makePartialTypeProvider(configuredProvider); final TypeProvider typeProvider = new CombinedTypeProvider(ImmutableList.of(partialProvider, configuredProvider)); - final Type messageType = - CelTypes.createMessage("dev.cel.testing.testdata.proto2.Proto2Message"); + final Type messageType = CelTypes.createMessage("google.api.expr.test.v1.proto2.TestAllTypes"); assertThat(typeProvider.lookupExtensionType("non.existent")).isNull(); ExtensionFieldType nestedExt = - typeProvider.lookupExtensionType("dev.cel.testing.testdata.proto2.nested_ext"); + typeProvider.lookupExtensionType("google.api.expr.test.v1.proto2.nested_ext"); assertThat(nestedExt).isNotNull(); assertThat(nestedExt.fieldType().type()).isEqualTo(messageType); assertThat(nestedExt.messageType()).isEqualTo(messageType); ExtensionFieldType int32Ext = - typeProvider.lookupExtensionType("dev.cel.testing.testdata.proto2.int32_ext"); + typeProvider.lookupExtensionType("google.api.expr.test.v1.proto2.int32_ext"); assertThat(int32Ext).isNotNull(); assertThat(int32Ext.fieldType().type()).isEqualTo(CelTypes.INT64); assertThat(int32Ext.messageType()).isEqualTo(messageType); ExtensionFieldType repeatedExt = - typeProvider.lookupExtensionType( - "dev.cel.testing.testdata.proto2.repeated_string_holder_ext"); + typeProvider.lookupExtensionType("google.api.expr.test.v1.proto2.repeated_test_all_types"); assertThat(repeatedExt).isNotNull(); assertThat(repeatedExt.fieldType().type()) .isEqualTo( CelTypes.createList( - CelTypes.createMessage("dev.cel.testing.testdata.proto2.StringHolder"))); + CelTypes.createMessage("google.api.expr.test.v1.proto2.TestAllTypes"))); assertThat(repeatedExt.messageType()).isEqualTo(messageType); // With leading dot '.'. assertThat( typeProvider.lookupExtensionType( - ".dev.cel.testing.testdata.proto2.repeated_string_holder_ext")) + ".google.api.expr.test.v1.proto2.repeated_test_all_types")) .isNotNull(); } diff --git a/checker/src/test/java/dev/cel/checker/ExprCheckerTest.java b/checker/src/test/java/dev/cel/checker/ExprCheckerTest.java index 9217942c1..c232441fc 100644 --- a/checker/src/test/java/dev/cel/checker/ExprCheckerTest.java +++ b/checker/src/test/java/dev/cel/checker/ExprCheckerTest.java @@ -31,6 +31,8 @@ import dev.cel.expr.Type; import dev.cel.expr.Type.AbstractType; import dev.cel.expr.Type.PrimitiveType; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; @@ -48,9 +50,7 @@ import dev.cel.testing.CelAdorner; import dev.cel.testing.CelBaselineTestCase; import dev.cel.testing.CelDebug; -import dev.cel.testing.testdata.proto2.Proto2Message; import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,7 +74,9 @@ public ExprCheckerTest(TestCase testCase) { /** Helper to run a test for configured instance variables. */ private void runTest() throws Exception { CelAbstractSyntaxTree ast = - prepareTest(Arrays.asList(TestAllTypes.getDescriptor(), Proto2Message.getDescriptor())); + prepareTest( + Arrays.asList( + TestAllTypes.getDescriptor(), TestAllTypesProto.TestAllTypes.getDescriptor())); if (ast != null) { testOutput() .println( @@ -150,7 +152,7 @@ public void operatorsBytes() throws Exception { @Test public void operatorsConditional() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "false ? x.single_timestamp : null"; runTest(); } @@ -161,19 +163,19 @@ public void operatorsConditional() throws Exception { @Test public void referenceTypeRelative() throws Exception { source = "proto3.TestAllTypes"; - container = "dev.cel.testing.testdata"; + container = "google.api.expr.test.v1.TestAllTypes"; runTest(); } @Test public void referenceTypeAbsolute() throws Exception { - source = ".dev.cel.testing.testdata.proto3.TestAllTypes"; + source = ".google.api.expr.test.v1.proto3.TestAllTypes"; runTest(); } @Test public void referenceValue() throws Exception { - declareVariable("container.x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("container.x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x"; container = "container"; runTest(); @@ -194,15 +196,15 @@ public void anyMessage() throws Exception { declareVariable("y", createWrapper(PrimitiveType.INT64)); source = "x == google.protobuf.Any{" - + "type_url:'types.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes'}" + + "type_url:'types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes'}" + " && x.single_nested_message.bb == 43 || x ==" - + " dev.cel.testing.testdata.proto3.TestAllTypes{} || y < x|| x >= x"; + + " google.api.expr.test.v1.proto3.TestAllTypes{} || y < x|| x >= x"; runTest(); } @Test public void messageFieldSelect() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_nested_message.bb == 43 && has(x.single_nested_message) && has(x.single_int32)" + " && has(x.repeated_int32) && has(x.map_int64_nested_type)"; @@ -211,7 +213,7 @@ public void messageFieldSelect() throws Exception { @Test public void messageFieldSelectError() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_nested_message.undefined == x.undefined"; runTest(); } @@ -221,7 +223,7 @@ public void messageFieldSelectError() throws Exception { @Test public void listOperators() throws Exception { - declareVariable("x", createList(createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"))); + declareVariable("x", createList(createMessage("google.api.expr.test.v1.proto3.TestAllTypes"))); source = "(x + x)[1].single_int32 == size(x)"; runTest(); @@ -231,14 +233,14 @@ public void listOperators() throws Exception { @Test public void listRepeatedOperators() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.repeated_int64[x.single_int32] == 23"; runTest(); } @Test public void listIndexTypeError() throws Exception { - declareVariable("x", createList(createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"))); + declareVariable("x", createList(createMessage("google.api.expr.test.v1.proto3.TestAllTypes"))); source = "x[1u]"; runTest(); } @@ -251,7 +253,7 @@ public void identError() throws Exception { @Test public void listElemTypeError() throws Exception { - declareVariable("x", createList(createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"))); + declareVariable("x", createList(createMessage("google.api.expr.test.v1.proto3.TestAllTypes"))); declareVariable("y", createList(CelTypes.INT64)); source = "x + y"; runTest(); @@ -264,7 +266,7 @@ public void listElemTypeError() throws Exception { public void mapOperators() throws Exception { declareVariable( "x", - createMap(CelTypes.STRING, createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"))); + createMap(CelTypes.STRING, createMessage("google.api.expr.test.v1.proto3.TestAllTypes"))); source = "x[\"a\"].single_int32 == 23"; runTest(); @@ -276,14 +278,14 @@ public void mapOperators() throws Exception { public void mapIndexTypeError() throws Exception { declareVariable( "x", - createMap(CelTypes.STRING, createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"))); + createMap(CelTypes.STRING, createMessage("google.api.expr.test.v1.proto3.TestAllTypes"))); source = "x[2].single_int32 == 23"; runTest(); } @Test public void mapEmpty() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "size(x.map_int64_nested_type) == 0"; runTest(); } @@ -293,14 +295,14 @@ public void mapEmpty() throws Exception { @Test public void wrapper() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_int64_wrapper + 1 != 23"; runTest(); } @Test public void equalsWrapper() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_int64_wrapper == 1 && " + "x.single_int32_wrapper != 2 && " @@ -316,18 +318,18 @@ public void equalsWrapper() throws Exception { @Test public void nullableWrapper() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_int64_wrapper == null"; runTest(); } @Test public void nullableMessage() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_nested_message != null"; runTest(); - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "null == TestAllTypes{} || TestAllTypes{} == null"; runTest(); } @@ -340,7 +342,7 @@ public void nullNull() throws Exception { @Test public void nullablePrimitiveError() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_int64 != null"; runTest(); } @@ -350,14 +352,14 @@ public void nullablePrimitiveError() throws Exception { @Test public void dynOperators() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_value + 1 / x.single_struct.y == 23"; runTest(); } @Test public void dynOperatorsAtRuntime() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto3.TestAllTypes")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto3.TestAllTypes")); source = "x.single_value[23] + x.single_struct['y']"; runTest(); } @@ -492,9 +494,9 @@ public void namespacedVariables() throws Exception { source = "x"; runTest(); - container = "dev.cel.testing.testdata.proto3"; - Type messageType = createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); - declareVariable("dev.cel.testing.testdata.proto3.msgVar", messageType); + container = "google.api.expr.test.v1.proto3"; + Type messageType = createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); + declareVariable("google.api.expr.test.v1.proto3.msgVar", messageType); source = "msgVar.single_int32"; runTest(); } @@ -531,7 +533,7 @@ public void userFunctionOverlaps() throws Exception { @Test public void userFunctionAddsOverload() throws Exception { - Type messageType = createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); + Type messageType = createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("x", messageType); declareFunction( "size", globalOverload("size_message", ImmutableList.of(messageType), CelTypes.INT64)); @@ -551,7 +553,7 @@ public void userFunctionAddsMacroError() throws Exception { @Test public void proto2PrimitiveField() throws Exception { - declareVariable("x", createMessage("dev.cel.testing.testdata.proto2.Proto2Message")); + declareVariable("x", createMessage("google.api.expr.test.v1.proto2.TestAllTypes")); source = "x.single_fixed32 != 0u && x.single_fixed64 > 1u && x.single_int32 != null"; runTest(); source = "x.nestedgroup.single_name == ''"; @@ -563,21 +565,21 @@ public void proto2PrimitiveField() throws Exception { @Test public void aggregateMessage() throws Exception { - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "TestAllTypes{single_int32: 1, single_int64: 2}"; runTest(); } @Test public void aggregateMessageFieldUndefinedError() throws Exception { - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "TestAllTypes{single_int32: 1, undefined: 2}"; runTest(); } @Test public void aggregateMessageFieldTypeError() throws Exception { - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "TestAllTypes{single_int32: 1u}"; runTest(); } @@ -661,7 +663,7 @@ public void types() throws Exception { @Test public void enumValues() throws Exception { - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "TestAllTypes.NestedEnum.BAR != 99"; runTest(); } @@ -684,7 +686,7 @@ public void nestedEnums() throws Exception { @Test public void globalEnumValues() throws Exception { - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "GlobalEnum.GAZ == 2"; runTest(); } @@ -724,7 +726,7 @@ public void conversions() throws Exception { @Test public void quantifiers() throws Exception { - Type messageType = createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); + Type messageType = createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("x", messageType); source = "x.repeated_int64.all(e, e > 0) " @@ -735,7 +737,7 @@ public void quantifiers() throws Exception { @Test public void quantifiersErrors() throws Exception { - Type messageType = createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); + Type messageType = createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("x", messageType); source = "x.all(e, 0)"; runTest(); @@ -743,7 +745,7 @@ public void quantifiersErrors() throws Exception { @Test public void mapExpr() throws Exception { - Type messageType = createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); + Type messageType = createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("x", messageType); source = "x.repeated_int64.map(x, double(x))"; runTest(); @@ -757,7 +759,7 @@ public void mapExpr() throws Exception { @Test public void mapFilterExpr() throws Exception { - Type messageType = createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); + Type messageType = createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("x", messageType); source = "x.repeated_int64.map(x, x > 0, double(x))"; runTest(); @@ -924,7 +926,7 @@ public void optionals() throws Exception { source = "{?'key': {'a': 'b'}.?value}.key"; runTest(); - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "TestAllTypes{?single_int32: {}.?i}"; runTest(); @@ -949,7 +951,7 @@ public void optionalErrors() throws Exception { source = "[?'value']"; runTest(); - container = "dev.cel.testing.testdata.proto3.TestAllTypesProto"; + container = "google.api.expr.test.v1.proto3.TestAllTypesProto"; source = "TestAllTypes{?single_int32: 1}"; runTest(); diff --git a/checker/src/test/java/dev/cel/checker/TypeProviderLegacyImplTest.java b/checker/src/test/java/dev/cel/checker/TypeProviderLegacyImplTest.java index bd6635666..9195bb3d5 100644 --- a/checker/src/test/java/dev/cel/checker/TypeProviderLegacyImplTest.java +++ b/checker/src/test/java/dev/cel/checker/TypeProviderLegacyImplTest.java @@ -18,14 +18,13 @@ import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; import dev.cel.expr.Type; +import com.google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.protobuf.Descriptors.Descriptor; import dev.cel.common.types.CelTypes; import dev.cel.common.types.ProtoMessageTypeProvider; -import dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage; -import dev.cel.testing.testdata.proto2.Proto2Message; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -34,10 +33,7 @@ public final class TypeProviderLegacyImplTest { private static final ImmutableList DESCRIPTORS = - ImmutableList.of( - TestAllTypes.getDescriptor(), - Proto2Message.getDescriptor(), - Proto2ExtensionScopedMessage.getDescriptor()); + ImmutableList.of(TestAllTypes.getDescriptor(), Proto2ExtensionScopedMessage.getDescriptor()); private final ProtoMessageTypeProvider proto2Provider = new ProtoMessageTypeProvider(DESCRIPTORS); @@ -60,7 +56,7 @@ public void lookupType() { public void lookupFieldNames() { Type nestedTestAllTypes = compatTypeProvider - .lookupType("dev.cel.testing.testdata.proto2.NestedTestAllTypes") + .lookupType("google.api.expr.test.v1.proto2.NestedTestAllTypes") .getType(); ImmutableSet fieldNames = compatTypeProvider.lookupFieldNames(nestedTestAllTypes); assertThat(fieldNames) @@ -72,7 +68,7 @@ public void lookupFieldNames() { public void lookupFieldType() { Type nestedTestAllTypes = compatTypeProvider - .lookupType("dev.cel.testing.testdata.proto2.NestedTestAllTypes") + .lookupType("google.api.expr.test.v1.proto2.NestedTestAllTypes") .getType(); assertThat(compatTypeProvider.lookupFieldType(nestedTestAllTypes, "payload")) .isEqualTo(descriptorTypeProvider.lookupFieldType(nestedTestAllTypes, "payload")); @@ -83,7 +79,7 @@ public void lookupFieldType() { @Test public void lookupFieldType_inputNotMessage() { Type globalEnumType = - compatTypeProvider.lookupType("dev.cel.testing.testdata.proto2.GlobalEnum").getType(); + compatTypeProvider.lookupType("google.api.expr.test.v1.proto2.GlobalEnum").getType(); assertThat(compatTypeProvider.lookupFieldType(globalEnumType, "payload")).isNull(); assertThat(compatTypeProvider.lookupFieldType(globalEnumType, "payload")) .isEqualTo(descriptorTypeProvider.lookupFieldType(globalEnumType, "payload")); @@ -92,47 +88,47 @@ public void lookupFieldType_inputNotMessage() { @Test public void lookupExtension() { TypeProvider.ExtensionFieldType extensionType = - compatTypeProvider.lookupExtensionType("dev.cel.testing.testdata.proto2.nested_enum_ext"); + compatTypeProvider.lookupExtensionType("google.api.expr.test.v1.proto2.nested_enum_ext"); assertThat(extensionType.messageType()) - .isEqualTo(CelTypes.createMessage("dev.cel.testing.testdata.proto2.Proto2Message")); + .isEqualTo(CelTypes.createMessage("google.api.expr.test.v1.proto2.TestAllTypes")); assertThat(extensionType.fieldType().type()).isEqualTo(CelTypes.INT64); assertThat(extensionType) .isEqualTo( descriptorTypeProvider.lookupExtensionType( - "dev.cel.testing.testdata.proto2.nested_enum_ext")); + "google.api.expr.test.v1.proto2.nested_enum_ext")); } @Test public void lookupEnumValue() { Integer enumValue = - compatTypeProvider.lookupEnumValue("dev.cel.testing.testdata.proto2.GlobalEnum.GAR"); + compatTypeProvider.lookupEnumValue("google.api.expr.test.v1.proto2.GlobalEnum.GAR"); assertThat(enumValue).isEqualTo(1); assertThat(enumValue) .isEqualTo( descriptorTypeProvider.lookupEnumValue( - "dev.cel.testing.testdata.proto2.GlobalEnum.GAR")); + "google.api.expr.test.v1.proto2.GlobalEnum.GAR")); } @Test public void lookupEnumValue_notFoundValue() { Integer enumValue = - compatTypeProvider.lookupEnumValue("dev.cel.testing.testdata.proto2.GlobalEnum.BAR"); + compatTypeProvider.lookupEnumValue("google.api.expr.test.v1.proto2.GlobalEnum.BAR"); assertThat(enumValue).isNull(); assertThat(enumValue) .isEqualTo( descriptorTypeProvider.lookupEnumValue( - "dev.cel.testing.testdata.proto2.GlobalEnum.BAR")); + "google.api.expr.test.v1.proto2.GlobalEnum.BAR")); } @Test public void lookupEnumValue_notFoundEnumType() { Integer enumValue = - compatTypeProvider.lookupEnumValue("dev.cel.testing.testdata.proto2.InvalidEnum.TEST"); + compatTypeProvider.lookupEnumValue("google.api.expr.test.v1.proto2.InvalidEnum.TEST"); assertThat(enumValue).isNull(); assertThat(enumValue) .isEqualTo( descriptorTypeProvider.lookupEnumValue( - "dev.cel.testing.testdata.proto2.InvalidEnum.TEST")); + "google.api.expr.test.v1.proto2.InvalidEnum.TEST")); } @Test diff --git a/checker/src/test/resources/aggregateMessage.baseline b/checker/src/test/resources/aggregateMessage.baseline index 646c6e15b..506b5deb6 100644 --- a/checker/src/test/resources/aggregateMessage.baseline +++ b/checker/src/test/resources/aggregateMessage.baseline @@ -3,5 +3,5 @@ Source: TestAllTypes{single_int32: 1, single_int64: 2} TestAllTypes{ single_int32:1~int, single_int64:2~int -}~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.TestAllTypes +}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes diff --git a/checker/src/test/resources/anyMessage.baseline b/checker/src/test/resources/anyMessage.baseline index 55aedb13f..83b50bac3 100644 --- a/checker/src/test/resources/anyMessage.baseline +++ b/checker/src/test/resources/anyMessage.baseline @@ -1,4 +1,4 @@ -Source: x == google.protobuf.Any{type_url:'types.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes'} && x.single_nested_message.bb == 43 || x == dev.cel.testing.testdata.proto3.TestAllTypes{} || y < x|| x >= x +Source: x == google.protobuf.Any{type_url:'types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes'} && x.single_nested_message.bb == 43 || x == google.api.expr.test.v1.proto3.TestAllTypes{} || y < x|| x >= x declare x { value any } @@ -12,7 +12,7 @@ _||_( _==_( x~any^x, google.protobuf.Any{ - type_url:"types.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes"~string + type_url:"types.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes"~string }~any^google.protobuf.Any )~bool^equals, _==_( @@ -22,7 +22,7 @@ _||_( )~bool^logical_and, _==_( x~any^x, - dev.cel.testing.testdata.proto3.TestAllTypes{}~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.TestAllTypes + google.api.expr.test.v1.proto3.TestAllTypes{}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes )~bool^equals )~bool^logical_or, _||_( diff --git a/checker/src/test/resources/dynOperators.baseline b/checker/src/test/resources/dynOperators.baseline index e95cbbb86..ae4ea2c41 100644 --- a/checker/src/test/resources/dynOperators.baseline +++ b/checker/src/test/resources/dynOperators.baseline @@ -1,14 +1,14 @@ Source: x.single_value + 1 / x.single_struct.y == 23 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _==_( _+_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_value~dyn, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_value~dyn, _/_( 1~int, - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_struct~map(string, dyn).y~dyn + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_struct~map(string, dyn).y~dyn )~int^divide_int64 )~int^add_int64, 23~int diff --git a/checker/src/test/resources/dynOperatorsAtRuntime.baseline b/checker/src/test/resources/dynOperatorsAtRuntime.baseline index 2a347d6ee..8730c3c35 100644 --- a/checker/src/test/resources/dynOperatorsAtRuntime.baseline +++ b/checker/src/test/resources/dynOperatorsAtRuntime.baseline @@ -1,15 +1,15 @@ Source: x.single_value[23] + x.single_struct['y'] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _+_( _[_]( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_value~dyn, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_value~dyn, 23~int )~dyn^index_list|index_map, _[_]( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_struct~map(string, dyn), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_struct~map(string, dyn), "y"~string )~dyn^index_map )~dyn^add_int64|add_uint64|add_double|add_string|add_bytes|add_list|add_timestamp_duration|add_duration_timestamp|add_duration_duration diff --git a/checker/src/test/resources/enumValues.baseline b/checker/src/test/resources/enumValues.baseline index 2bad4ad99..b861e12d7 100644 --- a/checker/src/test/resources/enumValues.baseline +++ b/checker/src/test/resources/enumValues.baseline @@ -1,6 +1,6 @@ Source: TestAllTypes.NestedEnum.BAR != 99 =====> _!=_( - dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR~int^dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR, + google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR, 99~int )~bool^not_equals diff --git a/checker/src/test/resources/equalsWrapper.baseline b/checker/src/test/resources/equalsWrapper.baseline index c069c9625..0f7fdbe4e 100644 --- a/checker/src/test/resources/equalsWrapper.baseline +++ b/checker/src/test/resources/equalsWrapper.baseline @@ -1,38 +1,38 @@ Source: x.single_int64_wrapper == 1 && x.single_int32_wrapper != 2 && x.single_double_wrapper != 2.0 && x.single_float_wrapper == 1.0 && x.single_uint32_wrapper == 1u && x.single_uint64_wrapper != 42u declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _&&_( _&&_( _&&_( _==_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), 1~int )~bool^equals, _!=_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_int32_wrapper~wrapper(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32_wrapper~wrapper(int), 2~int )~bool^not_equals )~bool^logical_and, _!=_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_double_wrapper~wrapper(double), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_double_wrapper~wrapper(double), 2.0~double )~bool^not_equals )~bool^logical_and, _&&_( _&&_( _==_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_float_wrapper~wrapper(double), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_float_wrapper~wrapper(double), 1.0~double )~bool^equals, _==_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_uint32_wrapper~wrapper(uint), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_uint32_wrapper~wrapper(uint), 1u~uint )~bool^equals )~bool^logical_and, _!=_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_uint64_wrapper~wrapper(uint), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_uint64_wrapper~wrapper(uint), 42u~uint )~bool^not_equals )~bool^logical_and diff --git a/checker/src/test/resources/globalEnumValues.baseline b/checker/src/test/resources/globalEnumValues.baseline index 87f242428..b2f7ac7dc 100644 --- a/checker/src/test/resources/globalEnumValues.baseline +++ b/checker/src/test/resources/globalEnumValues.baseline @@ -1,6 +1,6 @@ Source: GlobalEnum.GAZ == 2 =====> _==_( - dev.cel.testing.testdata.proto3.GlobalEnum.GAZ~int^dev.cel.testing.testdata.proto3.GlobalEnum.GAZ, + google.api.expr.test.v1.proto3.GlobalEnum.GAZ~int^google.api.expr.test.v1.proto3.GlobalEnum.GAZ, 2~int )~bool^equals diff --git a/checker/src/test/resources/jsonStructTypeError.baseline b/checker/src/test/resources/jsonStructTypeError.baseline index a345af322..83d6bd717 100644 --- a/checker/src/test/resources/jsonStructTypeError.baseline +++ b/checker/src/test/resources/jsonStructTypeError.baseline @@ -3,6 +3,6 @@ declare x { value google.protobuf.Struct } =====> -ERROR: test_location:1:10: found no matching overload for '_!=_' applied to '(google.protobuf.Value, dev.cel.testing.testdata.proto3.TestAllTypes)' (candidates: (%A3, %A3)) +ERROR: test_location:1:10: found no matching overload for '_!=_' applied to '(google.protobuf.Value, google.api.expr.test.v1.proto3.TestAllTypes)' (candidates: (%A3, %A3)) | x["iss"] != TestAllTypes{single_int32: 1} | .........^ diff --git a/checker/src/test/resources/listElemTypeError.baseline b/checker/src/test/resources/listElemTypeError.baseline index 666025b59..469e5b0e6 100644 --- a/checker/src/test/resources/listElemTypeError.baseline +++ b/checker/src/test/resources/listElemTypeError.baseline @@ -1,11 +1,11 @@ Source: x + y declare x { - value list(dev.cel.testing.testdata.proto3.TestAllTypes) + value list(google.api.expr.test.v1.proto3.TestAllTypes) } declare y { value list(int) } =====> -ERROR: test_location:1:3: found no matching overload for '_+_' applied to '(list(dev.cel.testing.testdata.proto3.TestAllTypes), list(int))' (candidates: (int, int),(uint, uint),(double, double),(string, string),(bytes, bytes),(list(%A0), list(%A0)),(google.protobuf.Timestamp, google.protobuf.Duration),(google.protobuf.Duration, google.protobuf.Timestamp),(google.protobuf.Duration, google.protobuf.Duration)) +ERROR: test_location:1:3: found no matching overload for '_+_' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), list(int))' (candidates: (int, int),(uint, uint),(double, double),(string, string),(bytes, bytes),(list(%A0), list(%A0)),(google.protobuf.Timestamp, google.protobuf.Duration),(google.protobuf.Duration, google.protobuf.Timestamp),(google.protobuf.Duration, google.protobuf.Duration)) | x + y | ..^ \ No newline at end of file diff --git a/checker/src/test/resources/listIndexTypeError.baseline b/checker/src/test/resources/listIndexTypeError.baseline index 3bab400ef..898590535 100644 --- a/checker/src/test/resources/listIndexTypeError.baseline +++ b/checker/src/test/resources/listIndexTypeError.baseline @@ -1,8 +1,8 @@ Source: x[1u] declare x { - value list(dev.cel.testing.testdata.proto3.TestAllTypes) + value list(google.api.expr.test.v1.proto3.TestAllTypes) } =====> -ERROR: test_location:1:2: found no matching overload for '_[_]' applied to '(list(dev.cel.testing.testdata.proto3.TestAllTypes), uint)' (candidates: (list(%A0), int),(map(%A1, %B2), %A1)) +ERROR: test_location:1:2: found no matching overload for '_[_]' applied to '(list(google.api.expr.test.v1.proto3.TestAllTypes), uint)' (candidates: (list(%A0), int),(map(%A1, %B2), %A1)) | x[1u] | .^ diff --git a/checker/src/test/resources/listOperators.baseline b/checker/src/test/resources/listOperators.baseline index 7b3a3c154..dba29ba4c 100644 --- a/checker/src/test/resources/listOperators.baseline +++ b/checker/src/test/resources/listOperators.baseline @@ -1,30 +1,30 @@ Source: (x + x)[1].single_int32 == size(x) declare x { - value list(dev.cel.testing.testdata.proto3.TestAllTypes) + value list(google.api.expr.test.v1.proto3.TestAllTypes) } =====> _==_( _[_]( _+_( - x~list(dev.cel.testing.testdata.proto3.TestAllTypes)^x, - x~list(dev.cel.testing.testdata.proto3.TestAllTypes)^x - )~list(dev.cel.testing.testdata.proto3.TestAllTypes)^add_list, + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x, + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x + )~list(google.api.expr.test.v1.proto3.TestAllTypes)^add_list, 1~int - )~dev.cel.testing.testdata.proto3.TestAllTypes^index_list.single_int32~int, + )~google.api.expr.test.v1.proto3.TestAllTypes^index_list.single_int32~int, size( - x~list(dev.cel.testing.testdata.proto3.TestAllTypes)^x + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x )~int^size_list )~bool^equals Source: x.size() == size(x) declare x { - value list(dev.cel.testing.testdata.proto3.TestAllTypes) + value list(google.api.expr.test.v1.proto3.TestAllTypes) } =====> _==_( - x~list(dev.cel.testing.testdata.proto3.TestAllTypes)^x.size()~int^list_size, + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x.size()~int^list_size, size( - x~list(dev.cel.testing.testdata.proto3.TestAllTypes)^x + x~list(google.api.expr.test.v1.proto3.TestAllTypes)^x )~int^size_list )~bool^equals diff --git a/checker/src/test/resources/listRepeatedOperators.baseline b/checker/src/test/resources/listRepeatedOperators.baseline index 6f5fa76c8..4fd1fe5d5 100644 --- a/checker/src/test/resources/listRepeatedOperators.baseline +++ b/checker/src/test/resources/listRepeatedOperators.baseline @@ -1,12 +1,12 @@ Source: x.repeated_int64[x.single_int32] == 23 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _==_( _[_]( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int64~list(int), - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_int32~int + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32~int )~int^index_list, 23~int )~bool^equals diff --git a/checker/src/test/resources/mapEmpty.baseline b/checker/src/test/resources/mapEmpty.baseline index db6d5b65b..a7dc95415 100644 --- a/checker/src/test/resources/mapEmpty.baseline +++ b/checker/src/test/resources/mapEmpty.baseline @@ -1,11 +1,11 @@ Source: size(x.map_int64_nested_type) == 0 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _==_( size( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.map_int64_nested_type~map(int, dev.cel.testing.testdata.proto3.NestedTestAllTypes) + x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type~map(int, google.api.expr.test.v1.proto3.NestedTestAllTypes) )~int^size_map, 0~int )~bool^equals diff --git a/checker/src/test/resources/mapExpr.baseline b/checker/src/test/resources/mapExpr.baseline index eb3739e61..4fabfed85 100644 --- a/checker/src/test/resources/mapExpr.baseline +++ b/checker/src/test/resources/mapExpr.baseline @@ -1,13 +1,13 @@ Source: x.repeated_int64.map(x, double(x)) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> __comprehension__( // Variable x, // Target - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), // Accumulator __result__, // Init @@ -28,7 +28,7 @@ __comprehension__( Source: [].map(x, [].map(y, x in y && y in x)) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> ERROR: test_location:1:33: found no matching overload for '@in' applied to '(list(%elem0), %elem0)' (candidates: (%A7, list(%A7)),(%A8, map(%A8, %B9))) @@ -37,7 +37,7 @@ ERROR: test_location:1:33: found no matching overload for '@in' applied to '(lis Source: [{}.map(c,c,c)]+[{}.map(c,c,c)] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _+_( diff --git a/checker/src/test/resources/mapFilterExpr.baseline b/checker/src/test/resources/mapFilterExpr.baseline index b7b56ee88..7e7c0175a 100644 --- a/checker/src/test/resources/mapFilterExpr.baseline +++ b/checker/src/test/resources/mapFilterExpr.baseline @@ -1,13 +1,13 @@ Source: x.repeated_int64.map(x, x > 0, double(x)) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> __comprehension__( // Variable x, // Target - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), // Accumulator __result__, // Init @@ -35,7 +35,7 @@ __comprehension__( Source: lists.filter(x, x > 1.5) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare lists { value dyn @@ -71,7 +71,7 @@ __comprehension__( Source: args.user["myextension"].customAttributes.filter(x, x.name == "hobbies") declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare lists { value dyn diff --git a/checker/src/test/resources/mapIndexTypeError.baseline b/checker/src/test/resources/mapIndexTypeError.baseline index b681e067d..ad31488db 100644 --- a/checker/src/test/resources/mapIndexTypeError.baseline +++ b/checker/src/test/resources/mapIndexTypeError.baseline @@ -1,8 +1,8 @@ Source: x[2].single_int32 == 23 declare x { - value map(string, dev.cel.testing.testdata.proto3.TestAllTypes) + value map(string, google.api.expr.test.v1.proto3.TestAllTypes) } =====> -ERROR: test_location:1:2: found no matching overload for '_[_]' applied to '(map(string, dev.cel.testing.testdata.proto3.TestAllTypes), int)' (candidates: (list(%A0), int),(map(%A1, %B2), %A1)) +ERROR: test_location:1:2: found no matching overload for '_[_]' applied to '(map(string, google.api.expr.test.v1.proto3.TestAllTypes), int)' (candidates: (list(%A0), int),(map(%A1, %B2), %A1)) | x[2].single_int32 == 23 | .^ diff --git a/checker/src/test/resources/mapOperators.baseline b/checker/src/test/resources/mapOperators.baseline index 703b78898..454d7f024 100644 --- a/checker/src/test/resources/mapOperators.baseline +++ b/checker/src/test/resources/mapOperators.baseline @@ -1,25 +1,25 @@ Source: x["a"].single_int32 == 23 declare x { - value map(string, dev.cel.testing.testdata.proto3.TestAllTypes) + value map(string, google.api.expr.test.v1.proto3.TestAllTypes) } =====> _==_( _[_]( - x~map(string, dev.cel.testing.testdata.proto3.TestAllTypes)^x, + x~map(string, google.api.expr.test.v1.proto3.TestAllTypes)^x, "a"~string - )~dev.cel.testing.testdata.proto3.TestAllTypes^index_map.single_int32~int, + )~google.api.expr.test.v1.proto3.TestAllTypes^index_map.single_int32~int, 23~int )~bool^equals Source: x.size() == size(x) declare x { - value map(string, dev.cel.testing.testdata.proto3.TestAllTypes) + value map(string, google.api.expr.test.v1.proto3.TestAllTypes) } =====> _==_( - x~map(string, dev.cel.testing.testdata.proto3.TestAllTypes)^x.size()~int^map_size, + x~map(string, google.api.expr.test.v1.proto3.TestAllTypes)^x.size()~int^map_size, size( - x~map(string, dev.cel.testing.testdata.proto3.TestAllTypes)^x + x~map(string, google.api.expr.test.v1.proto3.TestAllTypes)^x )~int^size_map )~bool^equals diff --git a/checker/src/test/resources/messageFieldSelect.baseline b/checker/src/test/resources/messageFieldSelect.baseline index dd4cf8723..8a219faaf 100644 --- a/checker/src/test/resources/messageFieldSelect.baseline +++ b/checker/src/test/resources/messageFieldSelect.baseline @@ -1,22 +1,22 @@ Source: x.single_nested_message.bb == 43 && has(x.single_nested_message) && has(x.single_int32) && has(x.repeated_int32) && has(x.map_int64_nested_type) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _&&_( _&&_( _&&_( _==_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_nested_message~dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage.bb~int, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message~google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage.bb~int, 43~int )~bool^equals, - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_nested_message~test-only~~bool + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message~test-only~~bool )~bool^logical_and, - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_int32~test-only~~bool + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int32~test-only~~bool )~bool^logical_and, _&&_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int32~test-only~~bool, - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.map_int64_nested_type~test-only~~bool + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int32~test-only~~bool, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.map_int64_nested_type~test-only~~bool )~bool^logical_and )~bool^logical_and diff --git a/checker/src/test/resources/messageFieldSelectError.baseline b/checker/src/test/resources/messageFieldSelectError.baseline index 3bb8538ad..8c1808f1d 100644 --- a/checker/src/test/resources/messageFieldSelectError.baseline +++ b/checker/src/test/resources/messageFieldSelectError.baseline @@ -1,6 +1,6 @@ Source: x.single_nested_message.undefined == x.undefined declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> ERROR: test_location:1:24: undefined field 'undefined' diff --git a/checker/src/test/resources/namespacedVariables.baseline b/checker/src/test/resources/namespacedVariables.baseline index 9e0ccfe85..ecb3cfc30 100644 --- a/checker/src/test/resources/namespacedVariables.baseline +++ b/checker/src/test/resources/namespacedVariables.baseline @@ -9,8 +9,8 @@ Source: msgVar.single_int32 declare ns.x { value int } -declare dev.cel.testing.testdata.proto3.msgVar { - value dev.cel.testing.testdata.proto3.TestAllTypes +declare google.api.expr.test.v1.proto3.msgVar { + value google.api.expr.test.v1.proto3.TestAllTypes } =====> -dev.cel.testing.testdata.proto3.msgVar~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.msgVar.single_int32~int +google.api.expr.test.v1.proto3.msgVar~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.msgVar.single_int32~int diff --git a/checker/src/test/resources/nestedEnums.baseline b/checker/src/test/resources/nestedEnums.baseline index 3a2869a75..98b5477c7 100644 --- a/checker/src/test/resources/nestedEnums.baseline +++ b/checker/src/test/resources/nestedEnums.baseline @@ -1,16 +1,16 @@ Source: x.single_nested_enum == TestAllTypes.NestedEnum.BAR declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _==_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_nested_enum~int, - dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR~int^dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_enum~int, + google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR )~bool^equals Source: single_nested_enum == TestAllTypes.NestedEnum.BAR declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare single_nested_enum { value int @@ -18,12 +18,12 @@ declare single_nested_enum { =====> _==_( single_nested_enum~int^single_nested_enum, - dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR~int^dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR + google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR )~bool^equals Source: TestAllTypes{single_nested_enum : TestAllTypes.NestedEnum.BAR}.single_nested_enum == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare single_nested_enum { value int @@ -31,7 +31,7 @@ declare single_nested_enum { =====> _==_( TestAllTypes{ - single_nested_enum:dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR~int^dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum.BAR - }~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.TestAllTypes.single_nested_enum~int, + single_nested_enum:google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR~int^google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum.BAR + }~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes.single_nested_enum~int, 1~int )~bool^equals diff --git a/checker/src/test/resources/nullableMessage.baseline b/checker/src/test/resources/nullableMessage.baseline index e2db74762..d6920cede 100644 --- a/checker/src/test/resources/nullableMessage.baseline +++ b/checker/src/test/resources/nullableMessage.baseline @@ -1,25 +1,25 @@ Source: x.single_nested_message != null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _!=_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_nested_message~dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_nested_message~google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage, null~null )~bool^not_equals Source: null == TestAllTypes{} || TestAllTypes{} == null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _||_( _==_( null~null, - TestAllTypes{}~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.TestAllTypes + TestAllTypes{}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes )~bool^equals, _==_( - TestAllTypes{}~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.TestAllTypes, + TestAllTypes{}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes, null~null )~bool^equals )~bool^logical_or diff --git a/checker/src/test/resources/nullablePrimitiveError.baseline b/checker/src/test/resources/nullablePrimitiveError.baseline index 43a50447f..b6e4a7dc7 100644 --- a/checker/src/test/resources/nullablePrimitiveError.baseline +++ b/checker/src/test/resources/nullablePrimitiveError.baseline @@ -1,6 +1,6 @@ Source: x.single_int64 != null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> ERROR: test_location:1:16: found no matching overload for '_!=_' applied to '(int, null)' (candidates: (%A0, %A0)) diff --git a/checker/src/test/resources/nullableWrapper.baseline b/checker/src/test/resources/nullableWrapper.baseline index 4e6deb477..f2e0165b0 100644 --- a/checker/src/test/resources/nullableWrapper.baseline +++ b/checker/src/test/resources/nullableWrapper.baseline @@ -1,10 +1,10 @@ Source: x.single_int64_wrapper == null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _==_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), null~null )~bool^equals diff --git a/checker/src/test/resources/operatorsConditional.baseline b/checker/src/test/resources/operatorsConditional.baseline index 96c64bbf6..72123b2ee 100644 --- a/checker/src/test/resources/operatorsConditional.baseline +++ b/checker/src/test/resources/operatorsConditional.baseline @@ -1,10 +1,10 @@ Source: false ? x.single_timestamp : null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _?_:_( false~bool, - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_timestamp~google.protobuf.Timestamp, + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_timestamp~google.protobuf.Timestamp, null~null )~google.protobuf.Timestamp^conditional diff --git a/checker/src/test/resources/optionals.baseline b/checker/src/test/resources/optionals.baseline index cc534f514..c78f5cc5a 100644 --- a/checker/src/test/resources/optionals.baseline +++ b/checker/src/test/resources/optionals.baseline @@ -77,7 +77,7 @@ TestAllTypes{ {}~map(dyn, int), "i" )~optional_type(int)^select_optional_field -}~dev.cel.testing.testdata.proto3.TestAllTypes^dev.cel.testing.testdata.proto3.TestAllTypes +}~google.api.expr.test.v1.proto3.TestAllTypes^google.api.expr.test.v1.proto3.TestAllTypes Source: [?a, ?b, 'world'] declare a { diff --git a/checker/src/test/resources/proto2PrimitiveField.baseline b/checker/src/test/resources/proto2PrimitiveField.baseline index 1842b1c5e..6d5351988 100644 --- a/checker/src/test/resources/proto2PrimitiveField.baseline +++ b/checker/src/test/resources/proto2PrimitiveField.baseline @@ -1,18 +1,18 @@ Source: x.single_fixed32 != 0u && x.single_fixed64 > 1u && x.single_int32 != null declare x { - value dev.cel.testing.testdata.proto2.Proto2Message + value google.api.expr.test.v1.proto2.TestAllTypes } =====> ERROR: test_location:1:67: found no matching overload for '_!=_' applied to '(int, null)' (candidates: (%A1, %A1)) - | x.single_fixed32 != 0u && x.single_fixed64 > 1u && x.single_int32 != null - | ..................................................................^ + | x.single_fixed32 != 0u && x.single_fixed64 > 1u && x.single_int32 != null + | ..................................................................^ Source: x.nestedgroup.single_name == '' declare x { - value dev.cel.testing.testdata.proto2.Proto2Message + value google.api.expr.test.v1.proto2.TestAllTypes } =====> _==_( - x~dev.cel.testing.testdata.proto2.Proto2Message^x.nestedgroup~dev.cel.testing.testdata.proto2.Proto2Message.NestedGroup.single_name~string, + x~google.api.expr.test.v1.proto2.TestAllTypes^x.nestedgroup~google.api.expr.test.v1.proto2.TestAllTypes.NestedGroup.single_name~string, ""~string )~bool^equals diff --git a/checker/src/test/resources/quantifiers.baseline b/checker/src/test/resources/quantifiers.baseline index 3f4d99bb5..b2d651c8c 100644 --- a/checker/src/test/resources/quantifiers.baseline +++ b/checker/src/test/resources/quantifiers.baseline @@ -1,6 +1,6 @@ Source: x.repeated_int64.all(e, e > 0) && x.repeated_int64.exists(e, e < 0) && x.repeated_int64.exists_one(e, e == 0) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _&&_( @@ -9,7 +9,7 @@ _&&_( // Variable e, // Target - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), // Accumulator __result__, // Init @@ -32,7 +32,7 @@ _&&_( // Variable e, // Target - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), // Accumulator __result__, // Init @@ -58,7 +58,7 @@ _&&_( // Variable e, // Target - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.repeated_int64~list(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.repeated_int64~list(int), // Accumulator __result__, // Init diff --git a/checker/src/test/resources/quantifiersErrors.baseline b/checker/src/test/resources/quantifiersErrors.baseline index 052d9a38c..2f6d1eac6 100644 --- a/checker/src/test/resources/quantifiersErrors.baseline +++ b/checker/src/test/resources/quantifiersErrors.baseline @@ -1,9 +1,9 @@ Source: x.all(e, 0) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> -ERROR: test_location:1:1: expression of type 'dev.cel.testing.testdata.proto3.TestAllTypes' cannot be range of a comprehension (must be list, map, or dynamic) +ERROR: test_location:1:1: expression of type 'google.api.expr.test.v1.proto3.TestAllTypes' cannot be range of a comprehension (must be list, map, or dynamic) | x.all(e, 0) | ^ ERROR: test_location:1:6: found no matching overload for '_&&_' applied to '(bool, int)' (candidates: (bool, bool)) diff --git a/checker/src/test/resources/referenceTypeAbsolute.baseline b/checker/src/test/resources/referenceTypeAbsolute.baseline index 12057f1ce..7bd4487e5 100644 --- a/checker/src/test/resources/referenceTypeAbsolute.baseline +++ b/checker/src/test/resources/referenceTypeAbsolute.baseline @@ -1,3 +1,3 @@ -Source: .dev.cel.testing.testdata.proto3.TestAllTypes +Source: .google.api.expr.test.v1.proto3.TestAllTypes =====> -dev.cel.testing.testdata.proto3.TestAllTypes~type(dev.cel.testing.testdata.proto3.TestAllTypes)^dev.cel.testing.testdata.proto3.TestAllTypes +google.api.expr.test.v1.proto3.TestAllTypes~type(google.api.expr.test.v1.proto3.TestAllTypes)^google.api.expr.test.v1.proto3.TestAllTypes diff --git a/checker/src/test/resources/referenceTypeRelative.baseline b/checker/src/test/resources/referenceTypeRelative.baseline index 80e386607..abe4260d5 100644 --- a/checker/src/test/resources/referenceTypeRelative.baseline +++ b/checker/src/test/resources/referenceTypeRelative.baseline @@ -1,3 +1,3 @@ Source: proto3.TestAllTypes =====> -dev.cel.testing.testdata.proto3.TestAllTypes~type(dev.cel.testing.testdata.proto3.TestAllTypes)^dev.cel.testing.testdata.proto3.TestAllTypes +google.api.expr.test.v1.proto3.TestAllTypes~type(google.api.expr.test.v1.proto3.TestAllTypes)^google.api.expr.test.v1.proto3.TestAllTypes diff --git a/checker/src/test/resources/referenceValue.baseline b/checker/src/test/resources/referenceValue.baseline index b6ed9f23b..a6ded5464 100644 --- a/checker/src/test/resources/referenceValue.baseline +++ b/checker/src/test/resources/referenceValue.baseline @@ -1,6 +1,6 @@ Source: x declare container.x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> -container.x~dev.cel.testing.testdata.proto3.TestAllTypes^container.x +container.x~google.api.expr.test.v1.proto3.TestAllTypes^container.x diff --git a/checker/src/test/resources/userFunctionAddsOverload.baseline b/checker/src/test/resources/userFunctionAddsOverload.baseline index 775194ce7..3a8cb44ad 100644 --- a/checker/src/test/resources/userFunctionAddsOverload.baseline +++ b/checker/src/test/resources/userFunctionAddsOverload.baseline @@ -1,14 +1,14 @@ Source: size(x) > 4 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare size { - function size_message (dev.cel.testing.testdata.proto3.TestAllTypes) -> int + function size_message (google.api.expr.test.v1.proto3.TestAllTypes) -> int } =====> _>_( size( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x + x~google.api.expr.test.v1.proto3.TestAllTypes^x )~int^size_message, 4~int )~bool^greater_int64 diff --git a/checker/src/test/resources/wrapper.baseline b/checker/src/test/resources/wrapper.baseline index f5370bcd7..2180c4a5f 100644 --- a/checker/src/test/resources/wrapper.baseline +++ b/checker/src/test/resources/wrapper.baseline @@ -1,11 +1,11 @@ Source: x.single_int64_wrapper + 1 != 23 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> _!=_( _+_( - x~dev.cel.testing.testdata.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), + x~google.api.expr.test.v1.proto3.TestAllTypes^x.single_int64_wrapper~wrapper(int), 1~int )~int^add_int64, 23~int diff --git a/common/resources/testdata/proto2/BUILD.bazel b/common/resources/testdata/proto2/BUILD.bazel deleted file mode 100644 index a4afac550..000000000 --- a/common/resources/testdata/proto2/BUILD.bazel +++ /dev/null @@ -1,20 +0,0 @@ -package( - default_applicable_licenses = ["//:license"], - default_testonly = True, - default_visibility = ["//visibility:public"], -) - -alias( - name = "test_all_types_java_proto", - actual = "//common/src/main/resources/testdata/proto2:test_all_types_java_proto", -) - -alias( - name = "messages_proto2_java_proto", - actual = "//common/src/main/resources/testdata/proto2:messages_proto2_java_proto", -) - -alias( - name = "messages_extensions_proto2_java_proto", - actual = "//common/src/main/resources/testdata/proto2:messages_extensions_proto2_java_proto", -) diff --git a/common/resources/testdata/proto3/BUILD.bazel b/common/resources/testdata/proto3/BUILD.bazel index 38b92096c..77d5160ac 100644 --- a/common/resources/testdata/proto3/BUILD.bazel +++ b/common/resources/testdata/proto3/BUILD.bazel @@ -9,11 +9,6 @@ alias( actual = "//common/src/main/resources/testdata/proto3:test_all_types_file_descriptor_set", ) -alias( - name = "test_all_types_java_proto", - actual = "//common/src/main/resources/testdata/proto3:test_all_types_java_proto", -) - alias( name = "standalone_global_enum_java_proto", actual = "//common/src/main/resources/testdata/proto3:standalone_global_enum_java_proto", diff --git a/common/src/main/resources/testdata/proto2/BUILD.bazel b/common/src/main/resources/testdata/proto2/BUILD.bazel deleted file mode 100644 index 6d374ad01..000000000 --- a/common/src/main/resources/testdata/proto2/BUILD.bazel +++ /dev/null @@ -1,59 +0,0 @@ -package( - default_applicable_licenses = [ - "//:license", - ], - default_testonly = True, - default_visibility = [ - "//common/resources/testdata/proto2:__pkg__", - ], -) - -proto_library( - name = "messages_proto2_proto", - srcs = [ - "messages_proto2.proto", - ], - deps = [ - ":test_all_types_proto", - ], -) - -java_proto_library( - name = "messages_proto2_java_proto", - deps = [":messages_proto2_proto"], -) - -proto_library( - name = "messages_extensions_proto2_proto", - srcs = [ - "messages_extensions_proto2.proto", - ], - deps = [ - ":messages_proto2_proto", - ":test_all_types_proto", - ], -) - -java_proto_library( - name = "messages_extensions_proto2_java_proto", - deps = [":messages_extensions_proto2_proto"], -) - -proto_library( - name = "test_all_types_proto", - srcs = [ - "test_all_types.proto", - ], - deps = [ - "@com_google_protobuf//:any_proto", - "@com_google_protobuf//:duration_proto", - "@com_google_protobuf//:struct_proto", - "@com_google_protobuf//:timestamp_proto", - "@com_google_protobuf//:wrappers_proto", - ], -) - -java_proto_library( - name = "test_all_types_java_proto", - deps = [":test_all_types_proto"], -) diff --git a/common/src/main/resources/testdata/proto2/messages_extensions_proto2.proto b/common/src/main/resources/testdata/proto2/messages_extensions_proto2.proto deleted file mode 100644 index d1c6ee06d..000000000 --- a/common/src/main/resources/testdata/proto2/messages_extensions_proto2.proto +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -syntax = "proto2"; - -import "common/src/main/resources/testdata/proto2/messages_proto2.proto"; -import "common/src/main/resources/testdata/proto2/test_all_types.proto"; - -package dev.cel.testing.testdata.proto2; - -option java_outer_classname = "MessagesProto2Extensions"; -option java_package = "dev.cel.testing.testdata.proto2"; -option java_multiple_files = true; - -// Package scoped extensions -extend Proto2Message { - optional Proto2Message nested_ext = 100; - optional int32 int32_ext = 101; - optional dev.cel.testing.testdata.proto2.TestAllTypes test_all_types_ext = - 102; - optional dev.cel.testing.testdata.proto2.TestAllTypes.NestedEnum - nested_enum_ext = 103; - repeated StringHolder repeated_string_holder_ext = 104; -} - -// Message scoped extensions -message Proto2ExtensionScopedMessage { - extend Proto2Message { - optional Proto2Message message_scoped_nested_ext = 105; - optional NestedMessageInsideExtensions nested_message_inside_ext = 106; - optional int64 int64_ext = 107; - optional string string_ext = 108; - } -} - -message NestedMessageInsideExtensions { - optional string field = 1; -} diff --git a/common/src/main/resources/testdata/proto2/messages_proto2.proto b/common/src/main/resources/testdata/proto2/messages_proto2.proto deleted file mode 100644 index 6f8f082e6..000000000 --- a/common/src/main/resources/testdata/proto2/messages_proto2.proto +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -// LINT: ALLOW_GROUPS -syntax = "proto2"; - -package dev.cel.testing.testdata.proto2; - -import "common/src/main/resources/testdata/proto2/test_all_types.proto"; - -option java_outer_classname = "MessagesProto2"; -option java_package = "dev.cel.testing.testdata.proto2"; -option java_multiple_files = true; - -message Proto2Message { - optional int32 single_int32 = 1; - optional fixed32 single_fixed32 = 2; - optional fixed64 single_fixed64 = 3; - optional dev.cel.testing.testdata.proto2.GlobalEnum single_enum = 4; - optional dev.cel.testing.testdata.proto2.NestedTestAllTypes - single_nested_test_all_types = 5; - - optional group NestedGroup = 6 { - optional int32 single_id = 7; - optional string single_name = 8; - } - - extensions 100 to max; -} - -message StringHolder { - optional string s = 1; -} diff --git a/common/src/main/resources/testdata/proto2/test_all_types.proto b/common/src/main/resources/testdata/proto2/test_all_types.proto deleted file mode 100644 index 7307b2970..000000000 --- a/common/src/main/resources/testdata/proto2/test_all_types.proto +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -// Keep this file synced with: -// https://github.com/google/cel-spec/blob/master/proto/test/v1/proto2/test_all_types.proto - -syntax = "proto2"; - -package dev.cel.testing.testdata.proto2; - -import "google/protobuf/any.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/struct.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/wrappers.proto"; - -option java_outer_classname = "TestAllTypesProto"; -option java_package = "dev.cel.testing.testdata.proto2"; - -// This proto includes every type of field in both singular and repeated -// forms. -message TestAllTypes { - message NestedMessage { - // The field name "b" fails to compile in proto1 because it conflicts with - // a local variable named "b" in one of the generated methods. - // This file needs to compile in proto1 to test backwards-compatibility. - optional int32 bb = 1; - } - - enum NestedEnum { - FOO = 0; - BAR = 1; - BAZ = 2; - } - - // Singular - optional int32 single_int32 = 1 [default = -32]; - optional int64 single_int64 = 2 [default = -64]; - optional uint32 single_uint32 = 3 [default = 32]; - optional uint64 single_uint64 = 4 [default = 64]; - optional sint32 single_sint32 = 5; - optional sint64 single_sint64 = 6; - optional fixed32 single_fixed32 = 7; - optional fixed64 single_fixed64 = 8; - optional sfixed32 single_sfixed32 = 9; - optional sfixed64 single_sfixed64 = 10; - optional float single_float = 11 [default = 3.0]; - optional double single_double = 12 [default = 6.4]; - optional bool single_bool = 13 [default = true]; - optional string single_string = 14 [default = "empty"]; - optional bytes single_bytes = 15 [default = "none"]; - - // Wellknown. - optional google.protobuf.Any single_any = 100; - optional google.protobuf.Duration single_duration = 101; - optional google.protobuf.Timestamp single_timestamp = 102; - optional google.protobuf.Struct single_struct = 103; - optional google.protobuf.Value single_value = 104; - optional google.protobuf.Int64Value single_int64_wrapper = 105; - optional google.protobuf.Int32Value single_int32_wrapper = 106; - optional google.protobuf.DoubleValue single_double_wrapper = 107; - optional google.protobuf.FloatValue single_float_wrapper = 108; - optional google.protobuf.UInt64Value single_uint64_wrapper = 109; - optional google.protobuf.UInt32Value single_uint32_wrapper = 110; - optional google.protobuf.StringValue single_string_wrapper = 111; - optional google.protobuf.BoolValue single_bool_wrapper = 112; - optional google.protobuf.BytesValue single_bytes_wrapper = 113; - optional google.protobuf.ListValue list_value = 114; - - // Nested messages - oneof nested_type { - NestedMessage single_nested_message = 21; - NestedEnum single_nested_enum = 22 [default = BAR]; - } - optional NestedMessage standalone_message = 23; - optional NestedEnum standalone_enum = 24; - - // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; - repeated sfixed32 repeated_sfixed32 = 39; - repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; - - // Repeated and nested - repeated NestedMessage repeated_nested_message = 51; - repeated NestedEnum repeated_nested_enum = 52; - repeated string repeated_string_piece = 53 [ctype = STRING_PIECE]; - repeated string repeated_cord = 54 [ctype = CORD]; - repeated NestedMessage repeated_lazy_message = 55; - - // Map - map map_string_string = 61; - map map_int64_nested_type = 62; -} - -// This proto includes a recursively nested message. -message NestedTestAllTypes { - optional NestedTestAllTypes child = 1; - optional TestAllTypes payload = 2; -} - -// This proto has a required field. -message TestRequired { - required int32 required_int32 = 1; -} - -// This proto tests that global enums are resolved correctly. -enum GlobalEnum { - GOO = 0; - GAR = 1; - GAZ = 2; -} diff --git a/common/src/main/resources/testdata/proto3/BUILD.bazel b/common/src/main/resources/testdata/proto3/BUILD.bazel index 2230ee37a..865c21d84 100644 --- a/common/src/main/resources/testdata/proto3/BUILD.bazel +++ b/common/src/main/resources/testdata/proto3/BUILD.bazel @@ -13,27 +13,6 @@ filegroup( srcs = ["test_all_types.fds"], ) -proto_library( - name = "test_all_types_proto", - srcs = [ - "test_all_types.proto", - ], - deps = [ - "@com_google_protobuf//:any_proto", - "@com_google_protobuf//:duration_proto", - "@com_google_protobuf//:struct_proto", - "@com_google_protobuf//:timestamp_proto", - "@com_google_protobuf//:wrappers_proto", - ], -) - -java_proto_library( - name = "test_all_types_java_proto", - tags = [ - ], - deps = [":test_all_types_proto"], -) - proto_library( name = "standalone_global_enum_proto", srcs = ["standalone_global_enum.proto"], diff --git a/common/src/main/resources/testdata/proto3/test_all_types.proto b/common/src/main/resources/testdata/proto3/test_all_types.proto deleted file mode 100644 index 2ed2d9900..000000000 --- a/common/src/main/resources/testdata/proto3/test_all_types.proto +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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. - -// Keep this file synced with: -// https://raw.githubusercontent.com/google/cel-spec/master/proto/test/v1/proto3/test_all_types.proto - -syntax = "proto3"; - -package dev.cel.testing.testdata.proto3; - -import "google/protobuf/any.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/struct.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/wrappers.proto"; - -option java_outer_classname = "TestAllTypesProto"; -option java_package = "dev.cel.testing.testdata.proto3"; - -// This proto includes every type of field in both singular and repeated -// forms. -message TestAllTypes { - message NestedMessage { - // The field name "b" fails to compile in proto1 because it conflicts with - // a local variable named "b" in one of the generated methods. - // This file needs to compile in proto1 to test backwards-compatibility. - int32 bb = 1; - } - - enum NestedEnum { - FOO = 0; - BAR = 1; - BAZ = 2; - } - - // Singular - int32 single_int32 = 1; - int64 single_int64 = 2; - uint32 single_uint32 = 3; - uint64 single_uint64 = 4; - sint32 single_sint32 = 5; - sint64 single_sint64 = 6; - fixed32 single_fixed32 = 7; - fixed64 single_fixed64 = 8; - sfixed32 single_sfixed32 = 9; - sfixed64 single_sfixed64 = 10; - float single_float = 11; - double single_double = 12; - bool single_bool = 13; - string single_string = 14; - bytes single_bytes = 15; - optional bool optional_bool = 16; - optional bool optional_string = 17; - - // Wellknown. - google.protobuf.Any single_any = 100; - google.protobuf.Duration single_duration = 101; - google.protobuf.Timestamp single_timestamp = 102; - google.protobuf.Struct single_struct = 103; - google.protobuf.Value single_value = 104; - google.protobuf.Int64Value single_int64_wrapper = 105; - google.protobuf.Int32Value single_int32_wrapper = 106; - google.protobuf.DoubleValue single_double_wrapper = 107; - google.protobuf.FloatValue single_float_wrapper = 108; - google.protobuf.UInt64Value single_uint64_wrapper = 109; - google.protobuf.UInt32Value single_uint32_wrapper = 110; - google.protobuf.StringValue single_string_wrapper = 111; - google.protobuf.BoolValue single_bool_wrapper = 112; - google.protobuf.BytesValue single_bytes_wrapper = 113; - google.protobuf.ListValue single_list_value = 114; - - // Nested messages - oneof nested_type { - NestedMessage single_nested_message = 21; - NestedEnum single_nested_enum = 22; - } - NestedMessage standalone_message = 23; - NestedEnum standalone_enum = 24; - - // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; - repeated sfixed32 repeated_sfixed32 = 39; - repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; - - // Repeated and nested - repeated NestedMessage repeated_nested_message = 51; - repeated NestedEnum repeated_nested_enum = 52; - repeated string repeated_string_piece = 53 [ctype = STRING_PIECE]; - repeated string repeated_cord = 54 [ctype = CORD]; - repeated NestedMessage repeated_lazy_message = 55; - - // Map - map map_int32_int64 = 56; - map map_string_string = 61; - map map_int64_nested_type = 62; - - oneof kind { - NestedTestAllTypes oneof_type = 63; - NestedMessage oneof_msg = 64; - bool oneof_bool = 65; - } -} - -// This proto includes a recursively nested message. -message NestedTestAllTypes { - NestedTestAllTypes child = 1; - TestAllTypes payload = 2; -} - -// This proto tests that global enums are resolved correctly. -enum GlobalEnum { - GOO = 0; - GAR = 1; - GAZ = 2; -} diff --git a/common/src/test/java/dev/cel/common/ast/BUILD.bazel b/common/src/test/java/dev/cel/common/ast/BUILD.bazel index 3f1868156..2097a25f7 100644 --- a/common/src/test/java/dev/cel/common/ast/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/ast/BUILD.bazel @@ -22,7 +22,6 @@ java_library( "//common/ast:expr_factory", "//common/ast:expr_v1alpha1_converter", "//common/ast:mutable_expr", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//compiler", "//compiler:compiler_builder", @@ -31,6 +30,7 @@ java_library( "//parser:operator", "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_guava_guava_testlib", diff --git a/common/src/test/java/dev/cel/common/ast/CelExprFormatterTest.java b/common/src/test/java/dev/cel/common/ast/CelExprFormatterTest.java index be0652982..fee0ef6fd 100644 --- a/common/src/test/java/dev/cel/common/ast/CelExprFormatterTest.java +++ b/common/src/test/java/dev/cel/common/ast/CelExprFormatterTest.java @@ -16,6 +16,7 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import dev.cel.common.CelAbstractSyntaxTree; @@ -27,7 +28,6 @@ import dev.cel.compiler.CelCompilerFactory; import dev.cel.extensions.CelOptionalLibrary; import dev.cel.parser.CelStandardMacro; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -173,7 +173,7 @@ public void list() throws Exception { public void struct() throws Exception { CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .addMessageTypes(TestAllTypes.getDescriptor()) .addLibraries(CelOptionalLibrary.INSTANCE) .build(); @@ -223,7 +223,7 @@ public void struct() throws Exception { public void map() throws Exception { CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .addMessageTypes(TestAllTypes.getDescriptor()) .addLibraries(CelOptionalLibrary.INSTANCE) .build(); diff --git a/common/src/test/java/dev/cel/common/ast/CelExprVisitorTest.java b/common/src/test/java/dev/cel/common/ast/CelExprVisitorTest.java index cdb3de525..f27c8a347 100644 --- a/common/src/test/java/dev/cel/common/ast/CelExprVisitorTest.java +++ b/common/src/test/java/dev/cel/common/ast/CelExprVisitorTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; import dev.cel.common.CelAbstractSyntaxTree; @@ -33,7 +34,6 @@ import dev.cel.compiler.CelCompilerFactory; import dev.cel.parser.CelStandardMacro; import dev.cel.parser.Operator; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Before; import org.junit.Test; diff --git a/common/src/test/java/dev/cel/common/internal/BUILD.bazel b/common/src/test/java/dev/cel/common/internal/BUILD.bazel index 5109b23ac..fa46ced6d 100644 --- a/common/src/test/java/dev/cel/common/internal/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/internal/BUILD.bazel @@ -25,16 +25,14 @@ java_library( "//common/internal:errors", "//common/internal:proto_equality", "//common/internal:proto_message_factory", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto2:test_all_types_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/src/test/resources:default_instance_message_test_protos_java_proto", "//common/src/test/resources:multi_file_java_proto", "//common/src/test/resources:service_conflicting_name_java_proto", "//common/src/test/resources:single_file_java_proto", "//common/testing", "@@protobuf~//java/core", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@com_google_googleapis//google/type:type_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", diff --git a/common/src/test/java/dev/cel/common/internal/CombinedDescriptorPoolTest.java b/common/src/test/java/dev/cel/common/internal/CombinedDescriptorPoolTest.java index a56bb2ed5..518c039e9 100644 --- a/common/src/test/java/dev/cel/common/internal/CombinedDescriptorPoolTest.java +++ b/common/src/test/java/dev/cel/common/internal/CombinedDescriptorPoolTest.java @@ -16,14 +16,13 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.Value; import dev.cel.common.CelDescriptorUtil; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto2.Proto2Message; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,19 +66,19 @@ public void findExtensionDescriptor_success() { CelDescriptorPool dynamicDescriptorPool = DefaultDescriptorPool.create( CelDescriptorUtil.getAllDescriptorsFromFileDescriptor( - MessagesProto2Extensions.getDescriptor().getFile())); + TestAllTypesExtensions.getDescriptor().getFile())); CombinedDescriptorPool combinedDescriptorPool = CombinedDescriptorPool.create( ImmutableList.of(DefaultDescriptorPool.INSTANCE, dynamicDescriptorPool)); Optional fieldDescriptor = combinedDescriptorPool.findExtensionDescriptor( - Proto2Message.getDescriptor(), "dev.cel.testing.testdata.proto2.test_all_types_ext"); + TestAllTypes.getDescriptor(), "google.api.expr.test.v1.proto2.test_all_types_ext"); assertThat(fieldDescriptor).isPresent(); assertThat(fieldDescriptor.get().isExtension()).isTrue(); assertThat(fieldDescriptor.get().getFullName()) - .isEqualTo("dev.cel.testing.testdata.proto2.test_all_types_ext"); + .isEqualTo("google.api.expr.test.v1.proto2.test_all_types_ext"); } @Test @@ -87,7 +86,7 @@ public void findExtensionDescriptor_returnsEmpty() { CelDescriptorPool dynamicDescriptorPool = DefaultDescriptorPool.create( CelDescriptorUtil.getAllDescriptorsFromFileDescriptor( - MessagesProto2Extensions.getDescriptor().getFile())); + TestAllTypesExtensions.getDescriptor().getFile())); CombinedDescriptorPool combinedDescriptorPool = CombinedDescriptorPool.create( ImmutableList.of(DefaultDescriptorPool.INSTANCE, dynamicDescriptorPool)); diff --git a/common/src/test/java/dev/cel/common/internal/DefaultInstanceMessageFactoryTest.java b/common/src/test/java/dev/cel/common/internal/DefaultInstanceMessageFactoryTest.java index a167190f9..c035db244 100644 --- a/common/src/test/java/dev/cel/common/internal/DefaultInstanceMessageFactoryTest.java +++ b/common/src/test/java/dev/cel/common/internal/DefaultInstanceMessageFactoryTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.util.Arrays.stream; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.MoreExecutors; import com.google.protobuf.Descriptors.Descriptor; @@ -31,7 +32,6 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import dev.cel.common.testdata.ProtoJavaApiVersion1.Proto2JavaVersion1Message; import dev.cel.common.testing.RepeatedTestProvider; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.ArrayList; import java.util.List; import java.util.Optional; diff --git a/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java b/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java index aef6140bf..16f170746 100644 --- a/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java +++ b/common/src/test/java/dev/cel/common/internal/DefaultMessageFactoryTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.UTF_8; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; import com.google.common.base.Ascii; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -29,7 +30,6 @@ import dev.cel.common.CelDescriptorUtil; import dev.cel.common.CelDescriptors; import dev.cel.common.internal.ProtoMessageFactory.CombinedMessageFactory; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -59,7 +59,7 @@ public void newBuilder_withDescriptor_producesNewMessageBuilder() { TestAllTypes.Builder builder = (TestAllTypes.Builder) - messageFactory.newBuilder("dev.cel.testing.testdata.proto2.TestAllTypes").get(); + messageFactory.newBuilder("google.api.expr.test.v1.proto2.TestAllTypes").get(); assertThat(builder.setSingleInt64(5L).build()) .isEqualTo(TestAllTypes.newBuilder().setSingleInt64(5L).build()); diff --git a/common/src/test/java/dev/cel/common/internal/ProtoEqualityTest.java b/common/src/test/java/dev/cel/common/internal/ProtoEqualityTest.java index 7cbabf9bc..722d088b0 100644 --- a/common/src/test/java/dev/cel/common/internal/ProtoEqualityTest.java +++ b/common/src/test/java/dev/cel/common/internal/ProtoEqualityTest.java @@ -16,14 +16,14 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.NestedEnum; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.NestedMessage; import com.google.protobuf.Any; import com.google.protobuf.DynamicMessage; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Struct; import com.google.protobuf.Value; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes.NestedEnum; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes.NestedMessage; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/common/src/test/java/dev/cel/common/navigation/BUILD.bazel b/common/src/test/java/dev/cel/common/navigation/BUILD.bazel index f79a59482..c754e80df 100644 --- a/common/src/test/java/dev/cel/common/navigation/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/navigation/BUILD.bazel @@ -17,12 +17,12 @@ java_library( "//common/navigation", "//common/navigation:common", "//common/navigation:mutable_navigation", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//compiler", "//compiler:compiler_builder", "//parser:macro", "//parser:operator", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", diff --git a/common/src/test/java/dev/cel/common/navigation/CelNavigableExprVisitorTest.java b/common/src/test/java/dev/cel/common/navigation/CelNavigableExprVisitorTest.java index 101fb9fdb..a8a35dd67 100644 --- a/common/src/test/java/dev/cel/common/navigation/CelNavigableExprVisitorTest.java +++ b/common/src/test/java/dev/cel/common/navigation/CelNavigableExprVisitorTest.java @@ -20,6 +20,7 @@ import static dev.cel.common.CelOverloadDecl.newMemberOverload; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.primitives.UnsignedLong; import com.google.testing.junit.testparameterinjector.TestParameter; @@ -38,7 +39,6 @@ import dev.cel.compiler.CelCompilerFactory; import dev.cel.parser.CelStandardMacro; import dev.cel.parser.Operator; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -580,7 +580,7 @@ public void messageConstruction_allNodesReturned() throws Exception { CelCompiler compiler = CelCompilerFactory.standardCelCompilerBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = compiler.compile("TestAllTypes{single_int64: 1}").getAst(); CelNavigableAst navigableAst = CelNavigableAst.fromAst(ast); @@ -603,7 +603,7 @@ public void messageConstruction_filterStruct_allNodesReturned() throws Exception CelCompiler compiler = CelCompilerFactory.standardCelCompilerBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = compiler.compile("TestAllTypes{single_int64: 1}").getAst(); CelNavigableAst navigableAst = CelNavigableAst.fromAst(ast); @@ -631,7 +631,7 @@ public void messageConstruction_preOrder_heightSet() throws Exception { CelCompiler compiler = CelCompilerFactory.standardCelCompilerBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = compiler.compile("TestAllTypes{single_int64: 1}").getAst(); CelNavigableAst navigableAst = CelNavigableAst.fromAst(ast); @@ -651,7 +651,7 @@ public void messageConstruction_postOrder_heightSet() throws Exception { CelCompiler compiler = CelCompilerFactory.standardCelCompilerBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = compiler.compile("TestAllTypes{single_int64: 1}").getAst(); CelNavigableAst navigableAst = CelNavigableAst.fromAst(ast); @@ -672,7 +672,7 @@ public void messageConstruction_maxIdsSet(@TestParameter TraversalOrder traversa CelCompiler compiler = CelCompilerFactory.standardCelCompilerBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = compiler.compile("TestAllTypes{single_int64: 1}").getAst(); CelNavigableAst navigableAst = CelNavigableAst.fromAst(ast); diff --git a/common/src/test/java/dev/cel/common/types/BUILD.bazel b/common/src/test/java/dev/cel/common/types/BUILD.bazel index 44f3fac01..432ff1570 100644 --- a/common/src/test/java/dev/cel/common/types/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/types/BUILD.bazel @@ -8,15 +8,14 @@ java_library( srcs = glob(["*.java"]), deps = [ "//:java_truth", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//common/types:cel_internal_types", "//common/types:cel_types", "//common/types:message_type_provider", "//common/types:type_providers", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:com_google_truth_extensions_truth_proto_extension", diff --git a/common/src/test/java/dev/cel/common/types/ProtoMessageTypeProviderTest.java b/common/src/test/java/dev/cel/common/types/ProtoMessageTypeProviderTest.java index f07a67b71..a79bb1ffe 100644 --- a/common/src/test/java/dev/cel/common/types/ProtoMessageTypeProviderTest.java +++ b/common/src/test/java/dev/cel/common/types/ProtoMessageTypeProviderTest.java @@ -17,12 +17,12 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import dev.cel.common.types.CelTypeProvider.CombinedCelTypeProvider; -import dev.cel.testing.testdata.proto2.MessagesProto2; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,7 +39,9 @@ public final class ProtoMessageTypeProviderTest { private final ProtoMessageTypeProvider proto2Provider = new ProtoMessageTypeProvider( ImmutableSet.of( - MessagesProto2.getDescriptor(), MessagesProto2Extensions.getDescriptor())); + TestAllTypes.getDescriptor().getFile(), + TestAllTypesProto.TestAllTypes.getDescriptor().getFile(), + TestAllTypesExtensions.getDescriptor())); @Test public void types_emptyTypeSet() { @@ -55,21 +57,21 @@ public void findType_emptyTypeSet() { public void types_allGlobalAndNestedDeclarations() { assertThat(proto3Provider.types().stream().map(CelType::name).collect(toImmutableList())) .containsAtLeast( - "dev.cel.testing.testdata.proto3.GlobalEnum", - "dev.cel.testing.testdata.proto3.TestAllTypes", - "dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage", - "dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum", - "dev.cel.testing.testdata.proto3.NestedTestAllTypes"); + "google.api.expr.test.v1.proto3.GlobalEnum", + "google.api.expr.test.v1.proto3.TestAllTypes", + "google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage", + "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum", + "google.api.expr.test.v1.proto3.NestedTestAllTypes"); } @Test public void findType_globalEnumWithAllNamesAndNumbers() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.GlobalEnum"); + proto3Provider.findType("google.api.expr.test.v1.proto3.GlobalEnum"); assertThat(celType).isPresent(); assertThat(celType.get()).isInstanceOf(EnumType.class); EnumType enumType = (EnumType) celType.get(); - assertThat(enumType.name()).isEqualTo("dev.cel.testing.testdata.proto3.GlobalEnum"); + assertThat(enumType.name()).isEqualTo("google.api.expr.test.v1.proto3.GlobalEnum"); assertThat(enumType.findNameByNumber(0)).hasValue("GOO"); assertThat(enumType.findNameByNumber(1)).hasValue("GAR"); assertThat(enumType.findNameByNumber(2)).hasValue("GAZ"); @@ -79,12 +81,11 @@ public void findType_globalEnumWithAllNamesAndNumbers() { @Test public void findType_nestedEnumWithAllNamesAndNumbers() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum"); + proto3Provider.findType("google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum"); assertThat(celType).isPresent(); assertThat(celType.get()).isInstanceOf(EnumType.class); EnumType enumType = (EnumType) celType.get(); - assertThat(enumType.name()) - .isEqualTo("dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum"); + assertThat(enumType.name()).isEqualTo("google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum"); assertThat(enumType.findNumberByName("FOO")).hasValue(0); assertThat(enumType.findNumberByName("BAR")).hasValue(1); assertThat(enumType.findNumberByName("BAZ")).hasValue(2); @@ -94,11 +95,11 @@ public void findType_nestedEnumWithAllNamesAndNumbers() { @Test public void findType_globalMessageTypeNoExtensions() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.NestedTestAllTypes"); + proto3Provider.findType("google.api.expr.test.v1.proto3.NestedTestAllTypes"); assertThat(celType).isPresent(); assertThat(celType.get()).isInstanceOf(ProtoMessageType.class); ProtoMessageType protoType = (ProtoMessageType) celType.get(); - assertThat(protoType.name()).isEqualTo("dev.cel.testing.testdata.proto3.NestedTestAllTypes"); + assertThat(protoType.name()).isEqualTo("google.api.expr.test.v1.proto3.NestedTestAllTypes"); assertThat(protoType.findField("payload")).isPresent(); assertThat(protoType.findField("child")).isPresent(); assertThat(protoType.findField("missing")).isEmpty(); @@ -109,101 +110,99 @@ public void findType_globalMessageTypeNoExtensions() { @Test public void findType_globalMessageWithExtensions() { Optional celType = - proto2Provider.findType("dev.cel.testing.testdata.proto2.Proto2Message"); + proto2Provider.findType("google.api.expr.test.v1.proto2.TestAllTypes"); assertThat(celType).isPresent(); assertThat(celType.get()).isInstanceOf(ProtoMessageType.class); ProtoMessageType protoType = (ProtoMessageType) celType.get(); - assertThat(protoType.name()).isEqualTo("dev.cel.testing.testdata.proto2.Proto2Message"); + assertThat(protoType.name()).isEqualTo("google.api.expr.test.v1.proto2.TestAllTypes"); assertThat(protoType.findField("single_int32")).isPresent(); - assertThat(protoType.findField("single_enum")).isPresent(); - assertThat(protoType.findField("single_nested_test_all_types")).isPresent(); + assertThat(protoType.findField("single_uint64")).isPresent(); + assertThat(protoType.findField("oneof_type")).isPresent(); assertThat(protoType.findField("nestedgroup")).isPresent(); - assertThat(protoType.findField("nested_ext")).isEmpty(); + assertThat(protoType.findField("nested_enum_ext")).isEmpty(); - assertThat(protoType.findExtension("dev.cel.testing.testdata.proto2.nested_ext")).isPresent(); - assertThat(protoType.findExtension("dev.cel.testing.testdata.proto2.int32_ext")).isPresent(); - assertThat(protoType.findExtension("dev.cel.testing.testdata.proto2.test_all_types_ext")) + assertThat(protoType.findExtension("google.api.expr.test.v1.proto2.nested_ext")).isPresent(); + assertThat(protoType.findExtension("google.api.expr.test.v1.proto2.int32_ext")).isPresent(); + assertThat(protoType.findExtension("google.api.expr.test.v1.proto2.test_all_types_ext")) .isPresent(); - assertThat(protoType.findExtension("dev.cel.testing.testdata.proto2.nested_enum_ext")) + assertThat(protoType.findExtension("google.api.expr.test.v1.proto2.nested_enum_ext")) .isPresent(); - assertThat( - protoType.findExtension("dev.cel.testing.testdata.proto2.repeated_string_holder_ext")) + assertThat(protoType.findExtension("google.api.expr.test.v1.proto2.repeated_test_all_types")) .isPresent(); - assertThat(protoType.findExtension("dev.cel.testing.testdata.proto2.Proto2Message.int32_ext")) + assertThat(protoType.findExtension("google.api.expr.test.v1.proto2.TestAllTypes.int32_ext")) .isEmpty(); Optional holderType = - proto2Provider.findType("dev.cel.testing.testdata.proto2.StringHolder"); + proto2Provider.findType("google.api.expr.test.v1.proto2.TestRequired"); assertThat(holderType).isPresent(); ProtoMessageType stringHolderType = (ProtoMessageType) holderType.get(); - assertThat(stringHolderType.findExtension("dev.cel.testing.testdata.proto2.nested_enum_ext")) + assertThat(stringHolderType.findExtension("google.api.expr.test.v1.proto2.nested_enum_ext")) .isEmpty(); } @Test public void findType_scopedMessageWithExtensions() { Optional celType = - proto2Provider.findType("dev.cel.testing.testdata.proto2.Proto2Message"); + proto2Provider.findType("google.api.expr.test.v1.proto2.TestAllTypes"); assertThat(celType).isPresent(); assertThat(celType.get()).isInstanceOf(ProtoMessageType.class); ProtoMessageType protoType = (ProtoMessageType) celType.get(); assertThat( protoType.findExtension( - "dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext")) + "google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext")) .isPresent(); assertThat( protoType.findExtension( - "dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.int64_ext")) + "google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext")) .isPresent(); assertThat( protoType.findExtension( - "dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.string_ext")) + "google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types")) .isPresent(); assertThat( protoType.findExtension( - "dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.nested_message_inside_ext")) + "google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext")) .isPresent(); } @Test public void findType_withRepeatedEnumField() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.TestAllTypes"); + proto3Provider.findType("google.api.expr.test.v1.proto3.TestAllTypes"); assertThat(celType).isPresent(); assertThat(celType.get()).isInstanceOf(ProtoMessageType.class); ProtoMessageType protoType = (ProtoMessageType) celType.get(); - assertThat(protoType.name()).isEqualTo("dev.cel.testing.testdata.proto3.TestAllTypes"); + assertThat(protoType.name()).isEqualTo("google.api.expr.test.v1.proto3.TestAllTypes"); assertThat(protoType.findField("repeated_nested_enum")).isPresent(); CelType fieldType = protoType.findField("repeated_nested_enum").get().type(); assertThat(fieldType.kind()).isEqualTo(CelKind.LIST); assertThat(fieldType.parameters()).hasSize(1); CelType elemType = fieldType.parameters().get(0); - assertThat(elemType.name()) - .isEqualTo("dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum"); + assertThat(elemType.name()).isEqualTo("google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum"); assertThat(elemType.kind()).isEqualTo(CelKind.INT); assertThat(elemType).isInstanceOf(EnumType.class); - assertThat(proto3Provider.findType("dev.cel.testing.testdata.proto3.TestAllTypes.NestedEnum")) + assertThat(proto3Provider.findType("google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum")) .hasValue(elemType); } @Test public void findType_withOneofField() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.TestAllTypes"); + proto3Provider.findType("google.api.expr.test.v1.proto3.TestAllTypes"); ProtoMessageType protoType = (ProtoMessageType) celType.get(); - assertThat(protoType.name()).isEqualTo("dev.cel.testing.testdata.proto3.TestAllTypes"); + assertThat(protoType.name()).isEqualTo("google.api.expr.test.v1.proto3.TestAllTypes"); assertThat(protoType.findField("single_nested_message").map(f -> f.type().name())) - .hasValue("dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage"); + .hasValue("google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage"); } @Test public void findType_withMapField() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.TestAllTypes"); + proto3Provider.findType("google.api.expr.test.v1.proto3.TestAllTypes"); ProtoMessageType protoType = (ProtoMessageType) celType.get(); CelType fieldType = protoType.findField("map_int64_nested_type").get().type(); @@ -213,14 +212,14 @@ public void findType_withMapField() { CelType valueType = fieldType.parameters().get(1); assertThat(keyType.name()).isEqualTo("int"); assertThat(keyType.kind()).isEqualTo(CelKind.INT); - assertThat(valueType.name()).isEqualTo("dev.cel.testing.testdata.proto3.NestedTestAllTypes"); + assertThat(valueType.name()).isEqualTo("google.api.expr.test.v1.proto3.NestedTestAllTypes"); assertThat(valueType.kind()).isEqualTo(CelKind.STRUCT); } @Test public void findType_withWellKnownTypes() { Optional celType = - proto3Provider.findType("dev.cel.testing.testdata.proto3.TestAllTypes"); + proto3Provider.findType("google.api.expr.test.v1.proto3.TestAllTypes"); ProtoMessageType protoType = (ProtoMessageType) celType.get(); assertThat(protoType.findField("single_any").map(f -> f.type())).hasValue(SimpleType.ANY); assertThat(protoType.findField("single_duration").map(f -> f.type())) @@ -228,7 +227,7 @@ public void findType_withWellKnownTypes() { assertThat(protoType.findField("single_timestamp").map(f -> f.type())) .hasValue(SimpleType.TIMESTAMP); assertThat(protoType.findField("single_value").map(f -> f.type())).hasValue(SimpleType.DYN); - assertThat(protoType.findField("single_list_value").map(f -> f.type())) + assertThat(protoType.findField("list_value").map(f -> f.type())) .hasValue(ListType.create(SimpleType.DYN)); assertThat(protoType.findField("single_struct").map(f -> f.type())) .hasValue(MapType.create(SimpleType.STRING, SimpleType.DYN)); diff --git a/common/src/test/java/dev/cel/common/values/BUILD.bazel b/common/src/test/java/dev/cel/common/values/BUILD.bazel index 388e4d6fb..92b71c6db 100644 --- a/common/src/test/java/dev/cel/common/values/BUILD.bazel +++ b/common/src/test/java/dev/cel/common/values/BUILD.bazel @@ -16,9 +16,6 @@ java_library( "//common/internal:default_message_factory", "//common/internal:dynamic_proto", "//common/internal:proto_message_factory", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto2:test_all_types_java_proto", "//common/types", "//common/types:type_providers", "//common/values", @@ -28,6 +25,7 @@ java_library( "//common/values:proto_message_value", "//common/values:proto_message_value_provider", "@@protobuf~//java/core", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_guava_guava_testlib", "@maven//:com_google_protobuf_protobuf_java_util", diff --git a/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java b/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java index 6dfb01344..0a2fe2ca6 100644 --- a/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java +++ b/common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java @@ -17,6 +17,8 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.primitives.UnsignedLong; @@ -32,9 +34,6 @@ import dev.cel.common.internal.DynamicProto; import dev.cel.common.internal.ProtoMessageFactory; import dev.cel.common.values.CelValueProvider.CombinedCelValueProvider; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto2.Proto2Message; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; import java.time.Duration; import java.time.Instant; import java.util.Optional; @@ -48,8 +47,7 @@ public class ProtoMessageValueProviderTest { DefaultDescriptorPool.create( CelDescriptorUtil.getAllDescriptorsFromFileDescriptor( ImmutableList.of( - TestAllTypes.getDescriptor().getFile(), - MessagesProto2Extensions.getDescriptor()))); + TestAllTypes.getDescriptor().getFile(), TestAllTypesExtensions.getDescriptor()))); private static final ProtoMessageFactory MESSAGE_FACTORY = DefaultMessageFactory.create(DESCRIPTOR_POOL); @@ -198,14 +196,14 @@ public void newValue_createProtoMessage_extensionFieldsPopulated() { (ProtoMessageValue) protoMessageValueProvider .newValue( - Proto2Message.getDescriptor().getFullName(), - ImmutableMap.of("dev.cel.testing.testdata.proto2.int32_ext", 1)) + TestAllTypes.getDescriptor().getFullName(), + ImmutableMap.of("google.api.expr.test.v1.proto2.int32_ext", 1)) .get(); assertThat(protoMessageValue.isZeroValue()).isFalse(); assertThat( protoMessageValue - .select(StringValue.create("dev.cel.testing.testdata.proto2.int32_ext")) + .select(StringValue.create("google.api.expr.test.v1.proto2.int32_ext")) .value()) .isEqualTo(1); } @@ -241,7 +239,7 @@ public void newValue_invalidField_throws() { .hasMessageThat() .isEqualTo( "field 'bogus' is not declared in message" - + " 'dev.cel.testing.testdata.proto2.TestAllTypes'"); + + " 'google.api.expr.test.v1.proto2.TestAllTypes'"); } @Test diff --git a/common/src/test/java/dev/cel/common/values/ProtoMessageValueTest.java b/common/src/test/java/dev/cel/common/values/ProtoMessageValueTest.java index 32f89e7a1..3a0f6e14e 100644 --- a/common/src/test/java/dev/cel/common/values/ProtoMessageValueTest.java +++ b/common/src/test/java/dev/cel/common/values/ProtoMessageValueTest.java @@ -17,6 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.NestedEnum; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.NestedMessage; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.primitives.UnsignedLong; @@ -41,11 +45,6 @@ import dev.cel.common.internal.DefaultMessageFactory; import dev.cel.common.internal.DynamicProto; import dev.cel.common.types.StructTypeReference; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto2.Proto2Message; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes.NestedEnum; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes.NestedMessage; import java.time.Duration; import java.time.Instant; import org.junit.Test; @@ -130,7 +129,7 @@ public void findField_fieldIsUndeclared_throwsException() { .hasMessageThat() .isEqualTo( "field 'bogus' is not declared in message" - + " 'dev.cel.testing.testdata.proto2.TestAllTypes'"); + + " 'google.api.expr.test.v1.proto2.TestAllTypes'"); } @Test @@ -138,27 +137,27 @@ public void findField_extensionField_success() { CelDescriptorPool descriptorPool = DefaultDescriptorPool.create( CelDescriptorUtil.getAllDescriptorsFromFileDescriptor( - ImmutableList.of(MessagesProto2Extensions.getDescriptor()))); + ImmutableList.of(TestAllTypesExtensions.getDescriptor()))); ProtoCelValueConverter protoCelValueConverter = ProtoCelValueConverter.newInstance( CelOptions.DEFAULT, DefaultDescriptorPool.INSTANCE, DynamicProto.create(DefaultMessageFactory.create(descriptorPool))); - Proto2Message proto2Message = - Proto2Message.newBuilder().setExtension(MessagesProto2Extensions.int32Ext, 1).build(); + TestAllTypes proto2Message = + TestAllTypes.newBuilder().setExtension(TestAllTypesExtensions.int32Ext, 1).build(); ProtoMessageValue protoMessageValue = ProtoMessageValue.create(proto2Message, descriptorPool, protoCelValueConverter); assertThat( - protoMessageValue.find(StringValue.create("dev.cel.testing.testdata.proto2.int32_ext"))) + protoMessageValue.find(StringValue.create("google.api.expr.test.v1.proto2.int32_ext"))) .isPresent(); } @Test public void findField_extensionField_throwsWhenDescriptorMissing() { - Proto2Message proto2Message = - Proto2Message.newBuilder().setExtension(MessagesProto2Extensions.int32Ext, 1).build(); + TestAllTypes proto2Message = + TestAllTypes.newBuilder().setExtension(TestAllTypesExtensions.int32Ext, 1).build(); ProtoMessageValue protoMessageValue = ProtoMessageValue.create( @@ -169,12 +168,12 @@ public void findField_extensionField_throwsWhenDescriptorMissing() { IllegalArgumentException.class, () -> protoMessageValue.select( - StringValue.create("dev.cel.testing.testdata.proto2.int32_ext"))); + StringValue.create("google.api.expr.test.v1.proto2.int32_ext"))); assertThat(exception) .hasMessageThat() .isEqualTo( - "field 'dev.cel.testing.testdata.proto2.int32_ext' is not declared in message" - + " 'dev.cel.testing.testdata.proto2.Proto2Message'"); + "field 'google.api.expr.test.v1.proto2.int32_ext' is not declared in message" + + " 'google.api.expr.test.v1.proto2.TestAllTypes'"); } private enum SelectFieldTestCase { diff --git a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel index 6cfbe3381..13411adb0 100644 --- a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel @@ -12,10 +12,6 @@ java_library( "//common", "//common:compiler_common", "//common:options", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto2:test_all_types_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//common/types:type_providers", "//compiler", @@ -30,6 +26,8 @@ java_library( "//runtime:interpreter_util", "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:com_google_testparameterinjector_test_parameter_injector", diff --git a/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java index 1eba6e22c..05caf8000 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameter; @@ -34,7 +35,6 @@ import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.runtime.CelRuntimeFactory; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; diff --git a/extensions/src/test/java/dev/cel/extensions/CelOptionalLibraryTest.java b/extensions/src/test/java/dev/cel/extensions/CelOptionalLibraryTest.java index 12eab47c4..c877555c2 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelOptionalLibraryTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelOptionalLibraryTest.java @@ -18,6 +18,8 @@ import static org.junit.Assert.assertThrows; import dev.cel.expr.Value; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.NestedMessage; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.primitives.UnsignedLong; @@ -48,8 +50,6 @@ import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.runtime.InterpreterUtil; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes.NestedMessage; import java.util.List; import java.util.Map; import java.util.Optional; @@ -94,7 +94,7 @@ private static CelBuilder newCelBuilder() { .setOptions( CelOptions.current().enableUnsignedLongs(true).enableTimestampEpoch(true).build()) .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .setContainer("dev.cel.testing.testdata.proto2") + .setContainer("google.api.expr.test.v1.proto2") .addMessageTypes(TestAllTypes.getDescriptor()) .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) .addCompilerLibraries(CelOptionalLibrary.INSTANCE); diff --git a/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java index d7b66cb1d..530ba73ae 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java @@ -17,6 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.NestedEnum; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.protobuf.Any; @@ -39,12 +43,6 @@ import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.runtime.CelRuntimeFactory; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto2.NestedMessageInsideExtensions; -import dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage; -import dev.cel.testing.testdata.proto2.Proto2Message; -import dev.cel.testing.testdata.proto2.StringHolder; -import dev.cel.testing.testdata.proto2.TestAllTypesProto.TestAllTypes.NestedEnum; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,47 +53,44 @@ public final class CelProtoExtensionsTest { CelCompilerFactory.standardCelCompilerBuilder() .addLibraries(CelExtensions.protos()) .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .addFileTypes(MessagesProto2Extensions.getDescriptor()) - .addVar( - "msg", StructTypeReference.create("dev.cel.testing.testdata.proto2.Proto2Message")) - .setContainer("dev.cel.testing.testdata.proto2") + .addFileTypes(TestAllTypesExtensions.getDescriptor()) + .addVar("msg", StructTypeReference.create("google.api.expr.test.v1.proto2.TestAllTypes")) + .setContainer("google.api.expr.test.v1.proto2") .build(); private static final CelRuntime CEL_RUNTIME = CelRuntimeFactory.standardCelRuntimeBuilder() - .addFileTypes(MessagesProto2Extensions.getDescriptor()) + .addFileTypes(TestAllTypesExtensions.getDescriptor()) .build(); - private static final Proto2Message PACKAGE_SCOPED_EXT_MSG = - Proto2Message.newBuilder() - .setExtension(MessagesProto2Extensions.int32Ext, 1) + private static final TestAllTypes PACKAGE_SCOPED_EXT_MSG = + TestAllTypes.newBuilder() + .setExtension(TestAllTypesExtensions.int32Ext, 1) .setExtension( - MessagesProto2Extensions.nestedExt, - Proto2Message.newBuilder().setSingleInt32(5).build()) - .setExtension(MessagesProto2Extensions.nestedEnumExt, NestedEnum.BAR) + TestAllTypesExtensions.nestedExt, TestAllTypes.newBuilder().setSingleInt32(5).build()) + .setExtension(TestAllTypesExtensions.nestedEnumExt, NestedEnum.BAR) .setExtension( - MessagesProto2Extensions.repeatedStringHolderExt, + TestAllTypesExtensions.repeatedTestAllTypes, ImmutableList.of( - StringHolder.newBuilder().setS("A").build(), - StringHolder.newBuilder().setS("B").build())) + TestAllTypes.newBuilder().setSingleString("A").build(), + TestAllTypes.newBuilder().setSingleString("B").build())) .build(); - private static final Proto2Message MESSAGE_SCOPED_EXT_MSG = - Proto2Message.newBuilder() + private static final TestAllTypes MESSAGE_SCOPED_EXT_MSG = + TestAllTypes.newBuilder() .setExtension( - Proto2ExtensionScopedMessage.nestedMessageInsideExt, - NestedMessageInsideExtensions.newBuilder().setField("test").build()) + Proto2ExtensionScopedMessage.messageScopedNestedExt, + TestAllTypes.newBuilder().setSingleString("test").build()) .setExtension(Proto2ExtensionScopedMessage.int64Ext, 1L) .build(); @Test - @TestParameters("{expr: 'proto.hasExt(msg, dev.cel.testing.testdata.proto2.int32_ext)'}") - @TestParameters("{expr: 'proto.hasExt(msg, dev.cel.testing.testdata.proto2.nested_ext)'}") - @TestParameters("{expr: 'proto.hasExt(msg, dev.cel.testing.testdata.proto2.nested_enum_ext)'}") + @TestParameters("{expr: 'proto.hasExt(msg, google.api.expr.test.v1.proto2.int32_ext)'}") + @TestParameters("{expr: 'proto.hasExt(msg, google.api.expr.test.v1.proto2.nested_ext)'}") + @TestParameters("{expr: 'proto.hasExt(msg, google.api.expr.test.v1.proto2.nested_enum_ext)'}") @TestParameters( - "{expr: 'proto.hasExt(msg, dev.cel.testing.testdata.proto2.repeated_string_holder_ext)'}") - @TestParameters( - "{expr: '!proto.hasExt(msg, dev.cel.testing.testdata.proto2.test_all_types_ext)'}") + "{expr: 'proto.hasExt(msg, google.api.expr.test.v1.proto2.repeated_test_all_types)'}") + @TestParameters("{expr: '!proto.hasExt(msg, google.api.expr.test.v1.proto2.test_all_types_ext)'}") public void hasExt_packageScoped_success(String expr) throws Exception { CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); boolean result = @@ -108,16 +103,16 @@ public void hasExt_packageScoped_success(String expr) throws Exception { @Test @TestParameters( "{expr: 'proto.hasExt(msg," - + " dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.nested_message_inside_ext)'}") + + " google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)'}") @TestParameters( "{expr: 'proto.hasExt(msg," - + " dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.int64_ext)'}") + + " google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext)'}") @TestParameters( "{expr: '!proto.hasExt(msg," - + " dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)'}") + + " google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types)'}") @TestParameters( "{expr: '!proto.hasExt(msg," - + " dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.string_ext)'}") + + " google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.nested_enum_ext)'}") public void hasExt_messageScoped_success(String expr) throws Exception { CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); boolean result = @@ -128,11 +123,11 @@ public void hasExt_messageScoped_success(String expr) throws Exception { } @Test - @TestParameters("{expr: 'msg.hasExt(''dev.cel.testing.testdata.proto2.int32_ext'', 0)'}") - @TestParameters("{expr: 'dyn(msg).hasExt(''dev.cel.testing.testdata.proto2.int32_ext'', 0)'}") + @TestParameters("{expr: 'msg.hasExt(''google.api.expr.test.v1.proto2.int32_ext'', 0)'}") + @TestParameters("{expr: 'dyn(msg).hasExt(''google.api.expr.test.v1.proto2.int32_ext'', 0)'}") public void hasExt_nonProtoNamespace_success(String expr) throws Exception { StructTypeReference proto2MessageTypeReference = - StructTypeReference.create("dev.cel.testing.testdata.proto2.Proto2Message"); + StructTypeReference.create("google.api.expr.test.v1.proto2.TestAllTypes"); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() .addLibraries(CelExtensions.protos()) @@ -151,9 +146,9 @@ public void hasExt_nonProtoNamespace_success(String expr) throws Exception { .addFunctionBindings( CelFunctionBinding.from( "msg_hasExt", - ImmutableList.of(Proto2Message.class, String.class, Long.class), + ImmutableList.of(TestAllTypes.class, String.class, Long.class), (arg) -> { - Proto2Message msg = (Proto2Message) arg[0]; + TestAllTypes msg = (TestAllTypes) arg[0]; String extensionField = (String) arg[1]; return msg.getAllFields().keySet().stream() .anyMatch(fd -> fd.getFullName().equals(extensionField)); @@ -175,25 +170,25 @@ public void hasExt_undefinedField_throwsException() { CelValidationException.class, () -> CEL_COMPILER - .compile("!proto.hasExt(msg, dev.cel.testing.testdata.proto2.undefined_field)") + .compile("!proto.hasExt(msg, google.api.expr.test.v1.proto2.undefined_field)") .getAst()); assertThat(exception) .hasMessageThat() - .contains("undefined field 'dev.cel.testing.testdata.proto2.undefined_field'"); + .contains("undefined field 'google.api.expr.test.v1.proto2.undefined_field'"); } @Test - @TestParameters("{expr: 'proto.getExt(msg, dev.cel.testing.testdata.proto2.int32_ext) == 1'}") + @TestParameters("{expr: 'proto.getExt(msg, google.api.expr.test.v1.proto2.int32_ext) == 1'}") @TestParameters( - "{expr: 'proto.getExt(msg, dev.cel.testing.testdata.proto2.nested_ext) ==" - + " Proto2Message{single_int32: 5}'}") + "{expr: 'proto.getExt(msg, google.api.expr.test.v1.proto2.nested_ext) ==" + + " TestAllTypes{single_int32: 5}'}") @TestParameters( - "{expr: 'proto.getExt(msg, dev.cel.testing.testdata.proto2.nested_enum_ext) ==" + "{expr: 'proto.getExt(msg, google.api.expr.test.v1.proto2.nested_enum_ext) ==" + " TestAllTypes.NestedEnum.BAR'}") @TestParameters( - "{expr: 'proto.getExt(msg, dev.cel.testing.testdata.proto2.repeated_string_holder_ext) ==" - + " [StringHolder{s: ''A''}, StringHolder{s: ''B''}]'}") + "{expr: 'proto.getExt(msg, google.api.expr.test.v1.proto2.repeated_test_all_types) ==" + + " [TestAllTypes{single_string: ''A''}, TestAllTypes{single_string: ''B''}]'}") public void getExt_packageScoped_success(String expr) throws Exception { CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); boolean result = @@ -206,11 +201,11 @@ public void getExt_packageScoped_success(String expr) throws Exception { @Test @TestParameters( "{expr: 'proto.getExt(msg," - + " dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.nested_message_inside_ext)" - + " == NestedMessageInsideExtensions{field: ''test''}'}") + + " google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)" + + " == TestAllTypes{single_string: ''test''}'}") @TestParameters( "{expr: 'proto.getExt(msg," - + " dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.int64_ext) == 1'}") + + " google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext) == 1'}") public void getExt_messageScopedSuccess(String expr) throws Exception { CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); boolean result = @@ -227,21 +222,20 @@ public void getExt_undefinedField_throwsException() { CelValidationException.class, () -> CEL_COMPILER - .compile("!proto.getExt(msg, dev.cel.testing.testdata.proto2.undefined_field)") + .compile("!proto.getExt(msg, google.api.expr.test.v1.proto2.undefined_field)") .getAst()); assertThat(exception) .hasMessageThat() - .contains("undefined field 'dev.cel.testing.testdata.proto2.undefined_field'"); + .contains("undefined field 'google.api.expr.test.v1.proto2.undefined_field'"); } @Test - @TestParameters("{expr: 'msg.getExt(''dev.cel.testing.testdata.proto2.int32_ext'', 0) == 1'}") - @TestParameters( - "{expr: 'dyn(msg).getExt(''dev.cel.testing.testdata.proto2.int32_ext'', 0) == 1'}") + @TestParameters("{expr: 'msg.getExt(''google.api.expr.test.v1.proto2.int32_ext'', 0) == 1'}") + @TestParameters("{expr: 'dyn(msg).getExt(''google.api.expr.test.v1.proto2.int32_ext'', 0) == 1'}") public void getExt_nonProtoNamespace_success(String expr) throws Exception { StructTypeReference proto2MessageTypeReference = - StructTypeReference.create("dev.cel.testing.testdata.proto2.Proto2Message"); + StructTypeReference.create("google.api.expr.test.v1.proto2.TestAllTypes"); CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() .addLibraries(CelExtensions.protos()) @@ -260,9 +254,9 @@ public void getExt_nonProtoNamespace_success(String expr) throws Exception { .addFunctionBindings( CelFunctionBinding.from( "msg_getExt", - ImmutableList.of(Proto2Message.class, String.class, Long.class), + ImmutableList.of(TestAllTypes.class, String.class, Long.class), (arg) -> { - Proto2Message msg = (Proto2Message) arg[0]; + TestAllTypes msg = (TestAllTypes) arg[0]; String extensionField = (String) arg[1]; FieldDescriptor extensionDescriptor = msg.getAllFields().keySet().stream() @@ -284,20 +278,20 @@ public void getExt_nonProtoNamespace_success(String expr) throws Exception { @Test public void getExt_onAnyPackedExtensionField_success() throws Exception { ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); - MessagesProto2Extensions.registerAllExtensions(extensionRegistry); + TestAllTypesExtensions.registerAllExtensions(extensionRegistry); Cel cel = CelFactory.standardCelBuilder() .addCompilerLibraries(CelExtensions.protos()) - .addFileTypes(MessagesProto2Extensions.getDescriptor()) + .addFileTypes(TestAllTypesExtensions.getDescriptor()) .setExtensionRegistry(extensionRegistry) .addVar( - "msg", StructTypeReference.create("dev.cel.testing.testdata.proto2.Proto2Message")) + "msg", StructTypeReference.create("google.api.expr.test.v1.proto2.TestAllTypes")) .build(); CelAbstractSyntaxTree ast = - cel.compile("proto.getExt(msg, dev.cel.testing.testdata.proto2.int32_ext)").getAst(); + cel.compile("proto.getExt(msg, google.api.expr.test.v1.proto2.int32_ext)").getAst(); Any anyMsg = Any.pack( - Proto2Message.newBuilder().setExtension(MessagesProto2Extensions.int32Ext, 1).build()); + TestAllTypes.newBuilder().setExtension(TestAllTypesExtensions.int32Ext, 1).build()); Long result = (Long) cel.createProgram(ast).eval(ImmutableMap.of("msg", anyMsg)); @@ -317,10 +311,10 @@ private enum ParseErrorTestCase { + " | ...................................................^"), FIELD_INSIDE_PRESENCE_TEST( "proto.getExt(Proto2ExtensionScopedMessage{}," - + " has(dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.int64_ext))", + + " has(google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext))", "ERROR: :1:49: invalid extension field\n" + " | proto.getExt(Proto2ExtensionScopedMessage{}," - + " has(dev.cel.testing.testdata.proto2.Proto2ExtensionScopedMessage.int64_ext))\n" + + " has(google.api.expr.test.v1.proto2.Proto2ExtensionScopedMessage.int64_ext))\n" + " | ................................................^"); private final String expr; diff --git a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java index 120ac25d6..ef11ff658 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameterInjector; @@ -36,7 +37,6 @@ import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.runtime.CelRuntimeFactory; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,7 +49,7 @@ public final class CelSetsExtensionsTest { CelCompilerFactory.standardCelCompilerBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) .setOptions(CEL_OPTIONS) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .addLibraries(CelExtensions.sets(CEL_OPTIONS)) .addVar("list", ListType.create(SimpleType.INT)) .addVar("subList", ListType.create(SimpleType.INT)) diff --git a/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java b/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java index 31cabdb9d..3a3983747 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; @@ -50,7 +51,6 @@ import dev.cel.parser.CelUnparser; import dev.cel.parser.CelUnparserFactory; import dev.cel.parser.Operator; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -64,7 +64,7 @@ public class AstMutatorTest { .addMessageTypes(TestAllTypes.getDescriptor()) .addCompilerLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.bindings()) .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .addVar("msg", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())) .addVar("x", SimpleType.INT) .build(); diff --git a/optimizer/src/test/java/dev/cel/optimizer/BUILD.bazel b/optimizer/src/test/java/dev/cel/optimizer/BUILD.bazel index 83ccd8a3c..322b642a7 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/BUILD.bazel +++ b/optimizer/src/test/java/dev/cel/optimizer/BUILD.bazel @@ -17,7 +17,6 @@ java_library( "//common/ast:mutable_expr", "//common/navigation", "//common/navigation:mutable_navigation", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//compiler", "//extensions", @@ -33,6 +32,7 @@ java_library( "//parser:operator", "//parser:unparser", "//runtime", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/BUILD.bazel b/optimizer/src/test/java/dev/cel/optimizer/optimizers/BUILD.bazel index e1ac3bd52..d988c4e56 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/BUILD.bazel +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/BUILD.bazel @@ -16,7 +16,6 @@ java_library( "//common:options", "//common/ast", "//common/navigation:mutable_navigation", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//extensions", "//extensions:optional_library", @@ -33,6 +32,7 @@ java_library( "@maven//:junit_junit", "@maven//:com_google_testparameterinjector_test_parameter_injector", "//:java_truth", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_guava_guava", ], ) diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java index 96040b508..b416eb2d5 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; @@ -39,7 +40,6 @@ import dev.cel.parser.CelUnparser; import dev.cel.parser.CelUnparserFactory; import dev.cel.runtime.CelRuntime.CelFunctionBinding; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,7 +58,7 @@ public class ConstantFoldingOptimizerTest { .addFunctionBindings( CelFunctionBinding.from("get_true_overload", ImmutableList.of(), unused -> true)) .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .addCompilerLibraries( CelExtensions.bindings(), CelOptionalLibrary.INSTANCE, diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index e2035be1b..9e67bda85 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -17,6 +17,8 @@ import static com.google.common.truth.Truth.assertThat; import static dev.cel.common.CelOverloadDecl.newGlobalOverload; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.NestedTestAllTypes; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.base.Ascii; import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameter; @@ -41,8 +43,6 @@ import dev.cel.parser.CelUnparserFactory; import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.testing.BaselineTestCase; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.NestedTestAllTypes; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Optional; import org.junit.Before; import org.junit.Test; @@ -320,7 +320,7 @@ private void runLargeTestCases(CelOptimizer celOptimizer) throws Exception { private static CelBuilder newCelBuilder() { return CelFactory.standardCelBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .setStandardMacros(CelStandardMacro.STANDARD_MACROS) .setOptions( CelOptions.current().enableTimestampEpoch(true).populateMacroCalls(true).build()) diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java index 3febca67c..2f196b292 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java @@ -18,6 +18,7 @@ import static dev.cel.common.CelOverloadDecl.newGlobalOverload; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -57,7 +58,6 @@ import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntime.CelFunctionBinding; import dev.cel.runtime.CelRuntimeFactory; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; diff --git a/policy/src/test/java/dev/cel/policy/BUILD.bazel b/policy/src/test/java/dev/cel/policy/BUILD.bazel index 4ae85cb55..dff3e974d 100644 --- a/policy/src/test/java/dev/cel/policy/BUILD.bazel +++ b/policy/src/test/java/dev/cel/policy/BUILD.bazel @@ -15,7 +15,6 @@ java_library( "//common", "//common:options", "//common/internal", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//compiler", "//extensions:optional_library", "//parser", @@ -32,6 +31,7 @@ java_library( "//policy:validation_exception", "//policy:value_string", "//runtime", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", diff --git a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java index bf435f90a..9ff04cfe4 100644 --- a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java +++ b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java @@ -19,6 +19,7 @@ import static dev.cel.policy.PolicyTestHelper.readFromYaml; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameter; @@ -39,7 +40,6 @@ import dev.cel.policy.PolicyTestHelper.PolicyTestSuite.PolicyTestSection.PolicyTestCase.PolicyTestInput; import dev.cel.policy.PolicyTestHelper.TestYamlPolicy; import dev.cel.runtime.CelRuntime.CelFunctionBinding; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.io.IOException; import java.util.Map; import java.util.Optional; diff --git a/policy/src/test/resources/pb/config.yaml b/policy/src/test/resources/pb/config.yaml index d412ec012..dc38a6a23 100644 --- a/policy/src/test/resources/pb/config.yaml +++ b/policy/src/test/resources/pb/config.yaml @@ -13,11 +13,11 @@ # limitations under the License. name: "pb" -container: "dev.cel.testing.testdata.proto3" +container: "google.api.expr.test.v1.proto3" extensions: - name: "strings" version: 2 variables: - name: "spec" type: - type_name: "dev.cel.testing.testdata.proto3.TestAllTypes" + type_name: "google.api.expr.test.v1.proto3.TestAllTypes" diff --git a/runtime/src/test/java/dev/cel/runtime/ActivationTest.java b/runtime/src/test/java/dev/cel/runtime/ActivationTest.java index 04bc1cfb2..003a72e05 100644 --- a/runtime/src/test/java/dev/cel/runtime/ActivationTest.java +++ b/runtime/src/test/java/dev/cel/runtime/ActivationTest.java @@ -16,12 +16,12 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.NestedTestAllTypes; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.NestedMessage; import com.google.common.primitives.UnsignedLong; import com.google.protobuf.NullValue; import dev.cel.common.CelOptions; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.NestedTestAllTypes; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes.NestedMessage; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel index dd188ea28..56e66137c 100644 --- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel @@ -28,9 +28,6 @@ java_library( "//common/internal:dynamic_proto", "//common/internal:proto_message_factory", "//common/internal:well_known_proto", - "//common/resources/testdata/proto2:messages_extensions_proto2_java_proto", - "//common/resources/testdata/proto2:messages_proto2_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types", "//common/types:cel_v1alpha1_types", "//compiler", @@ -44,6 +41,8 @@ java_library( "//runtime:unknown_attributes", "//runtime:unknown_options", "@@protobuf~//java/core", + "@cel_spec//proto/test/v1/proto2:test_all_types_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@com_google_googleapis//google/api/expr/v1alpha1:expr_java_proto", "@com_google_googleapis//google/rpc/context:attribute_context_java_proto", "@maven//:com_google_guava_guava", diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java index 2ce5e4d0b..5aecde577 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java @@ -16,11 +16,11 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import dev.cel.common.CelException; import dev.cel.compiler.CelCompiler; import dev.cel.compiler.CelCompilerFactory; import dev.cel.runtime.CelRuntime.CelFunctionBinding; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -75,7 +75,7 @@ public void toRuntimeBuilder_collectionProperties_copied() { assertThat(newRuntimeBuilder.getFunctionBindings()).hasSize(1); assertThat(newRuntimeBuilder.getRuntimeLibraries().build()).hasSize(1); - assertThat(newRuntimeBuilder.getFileTypes().build()).hasSize(6); + assertThat(newRuntimeBuilder.getFileTypes().build()).hasSize(8); } @Test diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java index fd4de8179..867a8ea06 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.api.expr.v1alpha1.Constant; import com.google.api.expr.v1alpha1.Expr; import com.google.api.expr.v1alpha1.Type.PrimitiveType; @@ -47,7 +48,6 @@ import dev.cel.compiler.CelCompilerFactory; import dev.cel.parser.CelStandardMacro; import dev.cel.parser.CelUnparserFactory; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.util.List; import java.util.Map; import java.util.Optional; @@ -279,7 +279,7 @@ public void trace_select() throws Exception { Cel cel = CelFactory.standardCelBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = cel.compile("TestAllTypes{single_int64: 3}.single_int64").getAst(); @@ -298,7 +298,7 @@ public void trace_struct() throws Exception { Cel cel = CelFactory.standardCelBuilder() .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer("dev.cel.testing.testdata.proto3") + .setContainer("google.api.expr.test.v1.proto3") .build(); CelAbstractSyntaxTree ast = cel.compile("TestAllTypes{}").getAst(); diff --git a/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java b/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java index afe7ca4c0..c4622a7ab 100644 --- a/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java +++ b/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java @@ -17,6 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat; +import com.google.api.expr.test.v1.proto2.TestAllTypesExtensions; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto; +import com.google.api.expr.test.v1.proto2.TestAllTypesProto.TestAllTypes.NestedGroup; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.protobuf.Any; @@ -38,11 +42,6 @@ // CEL-Internal-3 import dev.cel.common.internal.ProtoMessageFactory; import dev.cel.common.internal.WellKnownProto; -import dev.cel.testing.testdata.proto2.MessagesProto2; -import dev.cel.testing.testdata.proto2.MessagesProto2Extensions; -import dev.cel.testing.testdata.proto2.Proto2Message; -import dev.cel.testing.testdata.proto2.Proto2Message.NestedGroup; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -87,8 +86,10 @@ public void createMessageDynamic_success() { @Test public void createNestedGroup_success() throws Exception { - String groupType = "dev.cel.testing.testdata.proto2.Proto2Message.NestedGroup"; - provider = DynamicMessageFactory.typeProvider(ImmutableList.of(NestedGroup.getDescriptor())); + String groupType = "google.api.expr.test.v1.proto2.TestAllTypes.NestedGroup"; + provider = + DynamicMessageFactory.typeProvider( + ImmutableList.of(TestAllTypesProto.TestAllTypes.NestedGroup.getDescriptor())); Message message = (Message) provider.createMessage( @@ -173,7 +174,7 @@ public void selectField_nonProtoObjectError() { public void selectField_extensionUsingDynamicTypes() { CelDescriptors celDescriptors = CelDescriptorUtil.getAllDescriptorsFromFileDescriptor( - ImmutableList.of(MessagesProto2Extensions.getDescriptor())); + ImmutableList.of(TestAllTypesExtensions.getDescriptor())); CelDescriptorPool pool = DefaultDescriptorPool.create(celDescriptors); provider = @@ -183,10 +184,10 @@ public void selectField_extensionUsingDynamicTypes() { long result = (long) provider.selectField( - Proto2Message.newBuilder() - .setExtension(MessagesProto2Extensions.int32Ext, 10) + TestAllTypesProto.TestAllTypes.newBuilder() + .setExtension(TestAllTypesExtensions.int32Ext, 10) .build(), - MessagesProto2.getDescriptor().getPackage() + ".int32_ext"); + TestAllTypesProto.getDescriptor().getPackage() + ".int32_ext"); assertThat(result).isEqualTo(10); } diff --git a/runtime/src/test/java/dev/cel/runtime/MessageFactoryTest.java b/runtime/src/test/java/dev/cel/runtime/MessageFactoryTest.java index 701a1e9c0..b19434ff1 100644 --- a/runtime/src/test/java/dev/cel/runtime/MessageFactoryTest.java +++ b/runtime/src/test/java/dev/cel/runtime/MessageFactoryTest.java @@ -16,10 +16,10 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.collect.ImmutableList; import com.google.protobuf.Message; import dev.cel.runtime.MessageFactory.CombinedMessageFactory; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/runtime/src/test/java/dev/cel/runtime/async/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/async/BUILD.bazel index 599a76835..98a575c2e 100644 --- a/runtime/src/test/java/dev/cel/runtime/async/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/async/BUILD.bazel @@ -13,7 +13,6 @@ java_library( "//bundle:cel", "//common", "//common:options", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/testing", "//common/types", "//runtime", @@ -21,6 +20,7 @@ java_library( "//runtime:unknown_options", "//runtime/async", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_guava_guava", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", diff --git a/runtime/src/test/java/dev/cel/runtime/async/CelAsyncRuntimeImplTest.java b/runtime/src/test/java/dev/cel/runtime/async/CelAsyncRuntimeImplTest.java index 4eebb499b..fc9fcc3e4 100644 --- a/runtime/src/test/java/dev/cel/runtime/async/CelAsyncRuntimeImplTest.java +++ b/runtime/src/test/java/dev/cel/runtime/async/CelAsyncRuntimeImplTest.java @@ -23,6 +23,7 @@ import dev.cel.expr.Type; import dev.cel.expr.Type.ListType; import dev.cel.expr.Type.PrimitiveType; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import com.google.testing.junit.testparameterinjector.TestParameter; @@ -38,7 +39,6 @@ import dev.cel.runtime.CelEvaluationException; import dev.cel.runtime.UnknownContext; import dev.cel.runtime.async.CelAsyncRuntime.AsyncProgram; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; import java.time.Duration; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; diff --git a/runtime/src/test/resources/dynamicMessage_adapted.baseline b/runtime/src/test/resources/dynamicMessage_adapted.baseline index 21751184b..d4e7b12b2 100644 --- a/runtime/src/test/resources/dynamicMessage_adapted.baseline +++ b/runtime/src/test/resources/dynamicMessage_adapted.baseline @@ -1,10 +1,10 @@ Source: msg.single_any declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -53,7 +53,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -64,11 +64,11 @@ result: bb: 42 Source: msg.single_bool_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -117,7 +117,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -127,11 +127,11 @@ result: true Source: msg.single_bytes_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -180,7 +180,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -190,11 +190,11 @@ result: hi Source: msg.single_double_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -243,7 +243,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -253,11 +253,11 @@ result: -3.0 Source: msg.single_float_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -306,7 +306,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -316,11 +316,11 @@ result: 1.5 Source: msg.single_int32_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -369,7 +369,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -379,11 +379,11 @@ result: -12 Source: msg.single_int64_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -432,7 +432,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -442,11 +442,11 @@ result: -34 Source: msg.single_string_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -495,7 +495,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -505,11 +505,11 @@ result: hello Source: msg.single_uint32_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -558,7 +558,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -568,11 +568,11 @@ result: 12 Source: msg.single_uint64_wrapper declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -621,7 +621,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -631,11 +631,11 @@ result: 34 Source: msg.single_duration declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -684,7 +684,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -696,11 +696,11 @@ nanos: 20 Source: msg.single_timestamp declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -749,7 +749,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -761,11 +761,11 @@ nanos: 200 Source: msg.single_value declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -814,7 +814,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -824,11 +824,11 @@ result: a Source: msg.single_struct declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -877,7 +877,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } @@ -885,13 +885,13 @@ single_list_value { } result: {b=c} -Source: msg.single_list_value +Source: msg.list_value declare msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {msg=single_any { - type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage" + type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage" value: "\b*" } single_duration { @@ -940,7 +940,7 @@ single_bool_wrapper { single_bytes_wrapper { value: "hi" } -single_list_value { +list_value { values { string_value: "d" } diff --git a/runtime/src/test/resources/dynamicMessage_dynamicDescriptor.baseline b/runtime/src/test/resources/dynamicMessage_dynamicDescriptor.baseline index 6de5a507d..5d30b1fec 100644 --- a/runtime/src/test/resources/dynamicMessage_dynamicDescriptor.baseline +++ b/runtime/src/test/resources/dynamicMessage_dynamicDescriptor.baseline @@ -108,10 +108,10 @@ result: seconds: 100 Source: TestAllTypes { single_any: any_packed_test_msg }.single_any declare any_packed_test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> -bindings: {any_packed_test_msg=type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes" +bindings: {any_packed_test_msg=type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes" value: "r\005hello" } result: single_string: "hello" @@ -119,10 +119,10 @@ result: single_string: "hello" Source: dynamic_msg declare any_packed_test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare dynamic_msg { value dev.cel.testing.testdata.serialized.proto3.TestAllTypes @@ -141,10 +141,10 @@ result: map_string_string { Source: dynamic_msg.map_string_string declare any_packed_test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare dynamic_msg { value dev.cel.testing.testdata.serialized.proto3.TestAllTypes @@ -159,10 +159,10 @@ result: {foo=bar} Source: dynamic_msg.map_string_string['foo'] declare any_packed_test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare dynamic_msg { value dev.cel.testing.testdata.serialized.proto3.TestAllTypes @@ -177,16 +177,16 @@ result: bar Source: f_msg(dynamic_msg) declare any_packed_test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare dynamic_msg { value dev.cel.testing.testdata.serialized.proto3.TestAllTypes } declare f_msg { - function f_msg_generated (dev.cel.testing.testdata.proto3.TestAllTypes) -> bool + function f_msg_generated (google.api.expr.test.v1.proto3.TestAllTypes) -> bool function f_msg_dynamic (dev.cel.testing.testdata.serialized.proto3.TestAllTypes) -> bool } =====> @@ -200,16 +200,16 @@ result: true Source: f_msg(test_msg) declare any_packed_test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare test_msg { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare dynamic_msg { value dev.cel.testing.testdata.serialized.proto3.TestAllTypes } declare f_msg { - function f_msg_generated (dev.cel.testing.testdata.proto3.TestAllTypes) -> bool + function f_msg_generated (google.api.expr.test.v1.proto3.TestAllTypes) -> bool function f_msg_dynamic (dev.cel.testing.testdata.serialized.proto3.TestAllTypes) -> bool } =====> diff --git a/runtime/src/test/resources/extensionManipulation.baseline b/runtime/src/test/resources/extensionManipulation.baseline index 5c64f9bf8..50f7897e0 100644 --- a/runtime/src/test/resources/extensionManipulation.baseline +++ b/runtime/src/test/resources/extensionManipulation.baseline @@ -5,60 +5,60 @@ Source: [y.hasI(), y.getI() == 200, !n.hasI(), n.getI() == 0, y.hasN(), y.getN().getI() == 0, !y.getN().hasN(), y.getN().getN().getI() == 0, !n.hasN(), n.assignN(y).getN().hasN(), !n.clearN().hasN(), !y.clearN().hasN(), - n.getR() == [], y.getR().map(h, h.s) == ["alpha", "beta"], - n.assignR(["a", "b"].map(s, StringHolder{s:s})).getR().map(h, h.s) == ["a", "b"], + n.getR() == [], y.getR().map(h, h.single_string) == ["alpha", "beta"], + n.assignR(["a", "b"].map(s, TestAllTypes{single_string:s})).getR().map(h, h.single_string) == ["a", "b"], y.clearR().getR() == []] declare y { - value dev.cel.testing.testdata.proto2.Proto2Message + value google.api.expr.test.v1.proto3.TestAllTypes } declare n { - value dev.cel.testing.testdata.proto2.Proto2Message + value google.api.expr.test.v1.proto3.TestAllTypes } declare getI { - function getI dev.cel.testing.testdata.proto2.Proto2Message.() -> int + function getI google.api.expr.test.v1.proto3.TestAllTypes.() -> int } declare hasI { - function hasI dev.cel.testing.testdata.proto2.Proto2Message.() -> bool + function hasI google.api.expr.test.v1.proto3.TestAllTypes.() -> bool } declare assignI { - function assignI dev.cel.testing.testdata.proto2.Proto2Message.(int) -> dev.cel.testing.testdata.proto2.Proto2Message + function assignI google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearI { - function clearI dev.cel.testing.testdata.proto2.Proto2Message.() -> dev.cel.testing.testdata.proto2.Proto2Message + function clearI google.api.expr.test.v1.proto3.TestAllTypes.() -> google.api.expr.test.v1.proto3.TestAllTypes } declare getN { - function getN dev.cel.testing.testdata.proto2.Proto2Message.() -> dev.cel.testing.testdata.proto2.Proto2Message + function getN google.api.expr.test.v1.proto3.TestAllTypes.() -> google.api.expr.test.v1.proto3.TestAllTypes } declare hasN { - function hasN dev.cel.testing.testdata.proto2.Proto2Message.() -> bool + function hasN google.api.expr.test.v1.proto3.TestAllTypes.() -> bool } declare assignN { - function assignN dev.cel.testing.testdata.proto2.Proto2Message.(dev.cel.testing.testdata.proto2.Proto2Message) -> dev.cel.testing.testdata.proto2.Proto2Message + function assignN google.api.expr.test.v1.proto3.TestAllTypes.(google.api.expr.test.v1.proto3.TestAllTypes) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearN { - function clearN dev.cel.testing.testdata.proto2.Proto2Message.() -> dev.cel.testing.testdata.proto2.Proto2Message + function clearN google.api.expr.test.v1.proto3.TestAllTypes.() -> google.api.expr.test.v1.proto3.TestAllTypes } declare getR { - function getR dev.cel.testing.testdata.proto2.Proto2Message.() -> list(dev.cel.testing.testdata.proto2.StringHolder) + function getR google.api.expr.test.v1.proto3.TestAllTypes.() -> list(google.api.expr.test.v1.proto2.TestAllTypes) } declare assignR { - function assignR dev.cel.testing.testdata.proto2.Proto2Message.(list(dev.cel.testing.testdata.proto2.StringHolder)) -> dev.cel.testing.testdata.proto2.Proto2Message + function assignR google.api.expr.test.v1.proto3.TestAllTypes.(list(google.api.expr.test.v1.proto2.TestAllTypes)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearR { - function clearR dev.cel.testing.testdata.proto2.Proto2Message.() -> dev.cel.testing.testdata.proto2.Proto2Message + function clearR google.api.expr.test.v1.proto3.TestAllTypes.() -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {y=single_int32: 100 -[dev.cel.testing.testdata.proto2.nested_ext] { +[google.api.expr.test.v1.proto2.int32_ext]: 200 +[google.api.expr.test.v1.proto2.nested_ext] { single_int32: 50 } -[dev.cel.testing.testdata.proto2.int32_ext]: 200 -[dev.cel.testing.testdata.proto2.repeated_string_holder_ext] { - s: "alpha" +[google.api.expr.test.v1.proto2.repeated_test_all_types] { + single_string: "alpha" } -[dev.cel.testing.testdata.proto2.repeated_string_holder_ext] { - s: "beta" +[google.api.expr.test.v1.proto2.repeated_test_all_types] { + single_string: "alpha" } , n=single_int32: 50 } -result: [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true] +result: [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true] diff --git a/runtime/src/test/resources/fieldManipulation.baseline b/runtime/src/test/resources/fieldManipulation.baseline index acacef93f..7734ee7f4 100644 --- a/runtime/src/test/resources/fieldManipulation.baseline +++ b/runtime/src/test/resources/fieldManipulation.baseline @@ -1,18 +1,18 @@ Source: TestAllTypes{single_bool: true}.assignSingleInt64(1) == TestAllTypes{single_bool: true, single_int64: 1} declare assignSingleInt64 { - function assignSingleInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignSingleInt64 google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignRepeatedInt64 { - function assignRepeatedInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(list(int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignRepeatedInt64 google.api.expr.test.v1.proto3.TestAllTypes.(list(int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignMap { - function assignMap dev.cel.testing.testdata.proto3.TestAllTypes.(map(int, int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignMap google.api.expr.test.v1.proto3.TestAllTypes.(map(int, int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearField { - function clearField dev.cel.testing.testdata.proto3.TestAllTypes.(string) -> dev.cel.testing.testdata.proto3.TestAllTypes + function clearField google.api.expr.test.v1.proto3.TestAllTypes.(string) -> google.api.expr.test.v1.proto3.TestAllTypes } declare singletonInt64 { - function singletonInt64 (int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function singletonInt64 (int) -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -20,19 +20,19 @@ result: true Source: TestAllTypes{repeated_int64: [1, 2]}.assignRepeatedInt64([3, 1, 4]) == TestAllTypes{repeated_int64: [3, 1, 4]} declare assignSingleInt64 { - function assignSingleInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignSingleInt64 google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignRepeatedInt64 { - function assignRepeatedInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(list(int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignRepeatedInt64 google.api.expr.test.v1.proto3.TestAllTypes.(list(int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignMap { - function assignMap dev.cel.testing.testdata.proto3.TestAllTypes.(map(int, int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignMap google.api.expr.test.v1.proto3.TestAllTypes.(map(int, int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearField { - function clearField dev.cel.testing.testdata.proto3.TestAllTypes.(string) -> dev.cel.testing.testdata.proto3.TestAllTypes + function clearField google.api.expr.test.v1.proto3.TestAllTypes.(string) -> google.api.expr.test.v1.proto3.TestAllTypes } declare singletonInt64 { - function singletonInt64 (int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function singletonInt64 (int) -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -40,19 +40,19 @@ result: true Source: TestAllTypes{single_bool: true, single_int64: 1}.clearField("single_bool") == TestAllTypes{single_int64: 1} declare assignSingleInt64 { - function assignSingleInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignSingleInt64 google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignRepeatedInt64 { - function assignRepeatedInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(list(int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignRepeatedInt64 google.api.expr.test.v1.proto3.TestAllTypes.(list(int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignMap { - function assignMap dev.cel.testing.testdata.proto3.TestAllTypes.(map(int, int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignMap google.api.expr.test.v1.proto3.TestAllTypes.(map(int, int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearField { - function clearField dev.cel.testing.testdata.proto3.TestAllTypes.(string) -> dev.cel.testing.testdata.proto3.TestAllTypes + function clearField google.api.expr.test.v1.proto3.TestAllTypes.(string) -> google.api.expr.test.v1.proto3.TestAllTypes } declare singletonInt64 { - function singletonInt64 (int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function singletonInt64 (int) -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -60,19 +60,19 @@ result: true Source: TestAllTypes{single_bool: false}.assignMap({13: 26, 22: 42}).map_int32_int64[22] == 42 declare assignSingleInt64 { - function assignSingleInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignSingleInt64 google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignRepeatedInt64 { - function assignRepeatedInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(list(int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignRepeatedInt64 google.api.expr.test.v1.proto3.TestAllTypes.(list(int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignMap { - function assignMap dev.cel.testing.testdata.proto3.TestAllTypes.(map(int, int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignMap google.api.expr.test.v1.proto3.TestAllTypes.(map(int, int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearField { - function clearField dev.cel.testing.testdata.proto3.TestAllTypes.(string) -> dev.cel.testing.testdata.proto3.TestAllTypes + function clearField google.api.expr.test.v1.proto3.TestAllTypes.(string) -> google.api.expr.test.v1.proto3.TestAllTypes } declare singletonInt64 { - function singletonInt64 (int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function singletonInt64 (int) -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -80,19 +80,19 @@ result: true Source: TestAllTypes{single_bool: true, repeated_int64: [1, 2]}.clearField("repeated_int64") == TestAllTypes{single_bool: true} declare assignSingleInt64 { - function assignSingleInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignSingleInt64 google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignRepeatedInt64 { - function assignRepeatedInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(list(int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignRepeatedInt64 google.api.expr.test.v1.proto3.TestAllTypes.(list(int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignMap { - function assignMap dev.cel.testing.testdata.proto3.TestAllTypes.(map(int, int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignMap google.api.expr.test.v1.proto3.TestAllTypes.(map(int, int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearField { - function clearField dev.cel.testing.testdata.proto3.TestAllTypes.(string) -> dev.cel.testing.testdata.proto3.TestAllTypes + function clearField google.api.expr.test.v1.proto3.TestAllTypes.(string) -> google.api.expr.test.v1.proto3.TestAllTypes } declare singletonInt64 { - function singletonInt64 (int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function singletonInt64 (int) -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -100,19 +100,19 @@ result: true Source: singletonInt64(12) == TestAllTypes{single_int64: 12} declare assignSingleInt64 { - function assignSingleInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignSingleInt64 google.api.expr.test.v1.proto3.TestAllTypes.(int) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignRepeatedInt64 { - function assignRepeatedInt64 dev.cel.testing.testdata.proto3.TestAllTypes.(list(int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignRepeatedInt64 google.api.expr.test.v1.proto3.TestAllTypes.(list(int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare assignMap { - function assignMap dev.cel.testing.testdata.proto3.TestAllTypes.(map(int, int)) -> dev.cel.testing.testdata.proto3.TestAllTypes + function assignMap google.api.expr.test.v1.proto3.TestAllTypes.(map(int, int)) -> google.api.expr.test.v1.proto3.TestAllTypes } declare clearField { - function clearField dev.cel.testing.testdata.proto3.TestAllTypes.(string) -> dev.cel.testing.testdata.proto3.TestAllTypes + function clearField google.api.expr.test.v1.proto3.TestAllTypes.(string) -> google.api.expr.test.v1.proto3.TestAllTypes } declare singletonInt64 { - function singletonInt64 (int) -> dev.cel.testing.testdata.proto3.TestAllTypes + function singletonInt64 (int) -> google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} diff --git a/runtime/src/test/resources/has.baseline b/runtime/src/test/resources/has.baseline index 1d14601fc..3a32d3389 100644 --- a/runtime/src/test/resources/has.baseline +++ b/runtime/src/test/resources/has.baseline @@ -1,6 +1,6 @@ Source: has(x.single_int32) && !has(x.single_int64) && has(x.single_bool_wrapper) && has(x.single_int32_wrapper) && !has(x.single_int64_wrapper) && has(x.repeated_int32) && !has(x.repeated_int64) && has(x.optional_bool) && !has(x.optional_string) && has(x.oneof_bool) && !has(x.oneof_type) && has(x.map_int32_int64) && !has(x.map_string_string) && has(x.single_nested_message) && !has(x.single_duration) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_int32: 1 @@ -13,11 +13,11 @@ map_int32_int64 { key: 1 value: 2 } -oneof_bool: false single_int32_wrapper { value: 42 } single_bool_wrapper { } +oneof_bool: false } result: true diff --git a/runtime/src/test/resources/jsonValueTypes.baseline b/runtime/src/test/resources/jsonValueTypes.baseline index b6bb53e1f..9a116c090 100644 --- a/runtime/src/test/resources/jsonValueTypes.baseline +++ b/runtime/src/test/resources/jsonValueTypes.baseline @@ -1,6 +1,6 @@ Source: x.single_value declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_value { @@ -11,7 +11,7 @@ result: true Source: x.single_value == double(1) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_value { @@ -22,7 +22,7 @@ result: true Source: x.single_value == 1.1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_value { @@ -33,7 +33,7 @@ result: true Source: x.single_value == null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_value { @@ -44,7 +44,7 @@ result: true Source: x.single_value == 'hello' declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_value { @@ -55,7 +55,7 @@ result: true Source: x.single_value[0] == [['hello'], -1.1][0] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_value { @@ -77,7 +77,7 @@ result: true Source: x.single_struct.num == {'str': ['hello'], 'num': -1.1}['num'] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_struct { @@ -103,7 +103,7 @@ result: true Source: TestAllTypes{single_struct: TestAllTypes{single_value: {'str': ['hello']}}.single_value} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -123,7 +123,7 @@ result: single_struct { Source: pair(x.single_struct.str[0], 'val') declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare pair { function pair (string, string) -> dyn diff --git a/runtime/src/test/resources/lists.baseline b/runtime/src/test/resources/lists.baseline index d97984ed2..493b1c60a 100644 --- a/runtime/src/test/resources/lists.baseline +++ b/runtime/src/test/resources/lists.baseline @@ -1,6 +1,6 @@ Source: ([1, 2, 3] + x.repeated_int32)[3] == 4 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -12,7 +12,7 @@ result: true Source: !(y in [1, 2, 3]) && y in [4, 5, 6] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -23,7 +23,7 @@ result: true Source: TestAllTypes{repeated_int32: [1,2]}.repeated_int32[1] == 2 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -34,7 +34,7 @@ result: true Source: 1 in TestAllTypes{repeated_int32: [1,2]}.repeated_int32 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -45,7 +45,7 @@ result: true Source: !(4 in [1, 2, 3]) && 1 in [1, 2, 3] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -56,7 +56,7 @@ result: true Source: !(4 in list) && 1 in list declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -70,7 +70,7 @@ result: true Source: !(y in list) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -84,7 +84,7 @@ result: true Source: y in list declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -98,7 +98,7 @@ result: true Source: list[3] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int diff --git a/runtime/src/test/resources/maps.baseline b/runtime/src/test/resources/maps.baseline index da0f857ad..33c0cd0c7 100644 --- a/runtime/src/test/resources/maps.baseline +++ b/runtime/src/test/resources/maps.baseline @@ -1,6 +1,6 @@ Source: {1: 2, 3: 4}[3] == 4 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -8,7 +8,7 @@ result: true Source: 3 in {1: 2, 3: 4} && !(4 in {1: 2, 3: 4}) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -16,7 +16,7 @@ result: true Source: x.map_int32_int64[22] == 23 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=map_int32_int64 { @@ -28,7 +28,7 @@ result: true Source: TestAllTypes{map_int32_int64: {21: 22, 22: 23}}.map_int32_int64[22] == 23 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -36,7 +36,7 @@ result: true Source: TestAllTypes{oneof_type: NestedTestAllTypes{payload: x}}.oneof_type.payload.map_int32_int64[22] == 23 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=map_int32_int64 { @@ -48,7 +48,7 @@ result: true Source: !(4 in map) && 1 in map declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -62,7 +62,7 @@ result: true Source: !(y in {1: 4, 2: 3, 3: 2}) && y in {5: 3, 4: 2, 3: 3} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -76,7 +76,7 @@ result: true Source: !(y in map) && (y + 3) in map declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -90,7 +90,7 @@ result: true Source: TestAllTypes{map_int64_nested_type:{42:NestedTestAllTypes{payload:TestAllTypes{}}}} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -111,7 +111,7 @@ result: map_int64_nested_type { Source: {true: 1, false: 2, true: 3}[true] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int @@ -126,7 +126,7 @@ error_code: DUPLICATE_ATTRIBUTE Source: {b: 1, !b: 2, b: 3}[true] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare y { value int diff --git a/runtime/src/test/resources/messages.baseline b/runtime/src/test/resources/messages.baseline index df7a6579d..3a5dcf81b 100644 --- a/runtime/src/test/resources/messages.baseline +++ b/runtime/src/test/resources/messages.baseline @@ -1,6 +1,6 @@ Source: x.single_nested_message.bb == 43 && has(x.single_nested_message) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_nested_message { @@ -11,10 +11,10 @@ result: true Source: single_nested_message.bb == 43 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare single_nested_message { - value dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage + value google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage } =====> bindings: {single_nested_message=bb: 43 @@ -23,10 +23,10 @@ result: true Source: TestAllTypes{single_int64: 1, single_sfixed64: 2, single_int32: 2}.single_int32 == 2 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare single_nested_message { - value dev.cel.testing.testdata.proto3.TestAllTypes.NestedMessage + value google.api.expr.test.v1.proto3.TestAllTypes.NestedMessage } =====> bindings: {} diff --git a/runtime/src/test/resources/namespacedVariables.baseline b/runtime/src/test/resources/namespacedVariables.baseline index 1013e1b66..2b58cc41a 100644 --- a/runtime/src/test/resources/namespacedVariables.baseline +++ b/runtime/src/test/resources/namespacedVariables.baseline @@ -11,7 +11,7 @@ declare ns.x { value int } declare dev.cel.testing.testdata.proto3.msgVar { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {dev.cel.testing.testdata.proto3.msgVar=single_int32: 5 diff --git a/runtime/src/test/resources/nestedEnums.baseline b/runtime/src/test/resources/nestedEnums.baseline index 6dfee68f2..035a95726 100644 --- a/runtime/src/test/resources/nestedEnums.baseline +++ b/runtime/src/test/resources/nestedEnums.baseline @@ -1,6 +1,6 @@ Source: x.single_nested_enum == TestAllTypes.NestedEnum.BAR declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_nested_enum: BAR @@ -9,7 +9,7 @@ result: true Source: single_nested_enum == TestAllTypes.NestedEnum.BAR declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare single_nested_enum { value int @@ -20,7 +20,7 @@ result: true Source: TestAllTypes{single_nested_enum : TestAllTypes.NestedEnum.BAR}.single_nested_enum == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare single_nested_enum { value int diff --git a/runtime/src/test/resources/packUnpackAny.baseline b/runtime/src/test/resources/packUnpackAny.baseline index 2d57e9131..81e9f1a96 100644 --- a/runtime/src/test/resources/packUnpackAny.baseline +++ b/runtime/src/test/resources/packUnpackAny.baseline @@ -6,7 +6,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -26,7 +26,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -49,7 +49,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -71,7 +71,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -89,7 +89,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -108,13 +108,13 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) } =====> -bindings: {list=[type_url: "type.googleapis.com/dev.cel.testing.testdata.proto3.TestAllTypes" +bindings: {list=[type_url: "type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes" value: "\242\0062\n,type.googleapis.com/google.protobuf.Duration\022\002\bd" ], message=single_any { type_url: "type.googleapis.com/google.protobuf.Duration" @@ -131,7 +131,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -153,7 +153,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -175,7 +175,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -197,7 +197,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -218,7 +218,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -239,7 +239,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) @@ -260,7 +260,7 @@ declare d { value google.protobuf.Duration } declare message { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare list { value list(dyn) diff --git a/runtime/src/test/resources/typeComparisons.baseline b/runtime/src/test/resources/typeComparisons.baseline index 3af41c3da..915bdf4d9 100644 --- a/runtime/src/test/resources/typeComparisons.baseline +++ b/runtime/src/test/resources/typeComparisons.baseline @@ -23,7 +23,7 @@ Source: type(duration('10s')) == google.protobuf.Duration bindings: {} result: true -Source: type(TestAllTypes{}) == TestAllTypes && type(TestAllTypes{}) == proto3.TestAllTypes && type(TestAllTypes{}) == .dev.cel.testing.testdata.proto3.TestAllTypes && type(proto3.TestAllTypes{}) == TestAllTypes && type(proto3.TestAllTypes{}) == proto3.TestAllTypes && type(proto3.TestAllTypes{}) == .dev.cel.testing.testdata.proto3.TestAllTypes && type(.dev.cel.testing.testdata.proto3.TestAllTypes{}) == TestAllTypes && type(.dev.cel.testing.testdata.proto3.TestAllTypes{}) == proto3.TestAllTypes && type(.dev.cel.testing.testdata.proto3.TestAllTypes{}) == .dev.cel.testing.testdata.proto3.TestAllTypes +Source: type(TestAllTypes{}) == TestAllTypes && type(TestAllTypes{}) == proto3.TestAllTypes && type(TestAllTypes{}) == .google.api.expr.test.v1.proto3.TestAllTypes && type(proto3.TestAllTypes{}) == TestAllTypes && type(proto3.TestAllTypes{}) == proto3.TestAllTypes && type(proto3.TestAllTypes{}) == .google.api.expr.test.v1.proto3.TestAllTypes && type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == TestAllTypes && type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == proto3.TestAllTypes && type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == .google.api.expr.test.v1.proto3.TestAllTypes =====> bindings: {} result: true diff --git a/runtime/src/test/resources/unknownField.baseline b/runtime/src/test/resources/unknownField.baseline index 92f0a7385..5ddc80da5 100644 --- a/runtime/src/test/resources/unknownField.baseline +++ b/runtime/src/test/resources/unknownField.baseline @@ -1,6 +1,6 @@ Source: x.single_int32 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -11,7 +11,7 @@ result: unknown { Source: x.map_int32_int64[22] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -22,7 +22,7 @@ result: unknown { Source: x.repeated_nested_message[1] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -33,7 +33,7 @@ result: unknown { Source: x.single_timestamp.getSeconds() declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -44,7 +44,7 @@ result: unknown { Source: x.single_nested_message.bb declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -55,7 +55,7 @@ result: unknown { Source: {1: x.single_int32} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -66,7 +66,7 @@ result: unknown { Source: [1, x.single_int32] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} diff --git a/runtime/src/test/resources/unknownResultSet.baseline b/runtime/src/test/resources/unknownResultSet.baseline index eb7532b8b..2b2c61f62 100644 --- a/runtime/src/test/resources/unknownResultSet.baseline +++ b/runtime/src/test/resources/unknownResultSet.baseline @@ -1,6 +1,6 @@ Source: x.single_int32 == 1 && true declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -11,7 +11,7 @@ result: unknown { Source: x.single_int32 == 1 && false declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -19,7 +19,7 @@ result: false Source: x.single_int32 == 1 && x.single_int64 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -31,7 +31,7 @@ result: unknown { Source: x.single_int32 == 1 && x.single_timestamp <= timestamp("bad timestamp string") declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -42,7 +42,7 @@ result: unknown { Source: true && x.single_int32 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -53,7 +53,7 @@ result: unknown { Source: false && x.single_int32 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -61,7 +61,7 @@ result: false Source: x.single_timestamp <= timestamp("bad timestamp string") && x.single_int32 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -72,7 +72,7 @@ result: unknown { Source: x.single_timestamp <= timestamp("bad timestamp string") && x.single_timestamp > timestamp("another bad timestamp string") declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -81,7 +81,7 @@ error_code: BAD_FORMAT Source: x.single_int32 == 1 || x.single_string == "test" declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -93,7 +93,7 @@ result: unknown { Source: x.single_int32 == 1 || x.single_string != "test" declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -105,7 +105,7 @@ result: unknown { Source: x.single_int32 == 1 || x.single_int64 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -117,7 +117,7 @@ result: unknown { Source: x.single_int32 == 1 || x.single_timestamp <= timestamp("bad timestamp string") declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -128,7 +128,7 @@ result: unknown { Source: true || x.single_int32 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -136,7 +136,7 @@ result: true Source: false || x.single_int32 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -147,7 +147,7 @@ result: unknown { Source: x.single_timestamp <= timestamp("bad timestamp string") || x.single_int32 == 1 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -158,7 +158,7 @@ result: unknown { Source: x.single_timestamp <= timestamp("bad timestamp string") || x.single_timestamp > timestamp("another bad timestamp string") declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {} @@ -167,7 +167,7 @@ error_code: BAD_FORMAT Source: x.single_int32.f(1) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -181,7 +181,7 @@ result: unknown { Source: 1.f(x.single_int32) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -195,7 +195,7 @@ result: unknown { Source: x.single_int64.f(x.single_int32) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -210,7 +210,7 @@ result: unknown { Source: x declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -228,7 +228,7 @@ result: unknown { Source: x declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -244,7 +244,7 @@ result: unknown { Source: x.map_int32_int64.map(x, x > 0, x + 1) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -258,7 +258,7 @@ result: unknown { Source: [0, 2, 4].exists(z, z == 2 || z == x.single_int32) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -269,7 +269,7 @@ result: true Source: [0, 2, 4].exists(z, z == x.single_int32) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -283,7 +283,7 @@ result: unknown { Source: [0, 2, 4].exists_one(z, z == 0 || (z == 2 && z == x.single_int32) || (z == 4 && z == x.single_int64)) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -297,7 +297,7 @@ result: unknown { Source: [0, 2].all(z, z == 2 || z == x.single_int32) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -311,7 +311,7 @@ result: unknown { Source: [0, 2, 4].filter(z, z == 0 || (z == 2 && z == x.single_int32) || (z == 4 && z == x.single_int64)) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -325,7 +325,7 @@ result: unknown { Source: [0, 2, 4].map(z, z == 0 || (z == 2 && z == x.single_int32) || (z == 4 && z == x.single_int64)) declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -340,7 +340,7 @@ result: unknown { Source: x.single_int32 == 1 ? 1 : 2 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -354,7 +354,7 @@ result: unknown { Source: true ? x.single_int32 : 2 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -368,7 +368,7 @@ result: unknown { Source: true ? 1 : x.single_int32 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -379,7 +379,7 @@ result: 1 Source: false ? x.single_int32 : 2 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -390,7 +390,7 @@ result: 2 Source: false ? 1 : x.single_int32 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -404,7 +404,7 @@ result: unknown { Source: x.single_int64 == 1 ? x.single_int32 : x.single_int32 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -418,7 +418,7 @@ result: unknown { Source: {x.single_int32: 2, 3: 4} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -432,7 +432,7 @@ result: unknown { Source: {1: x.single_int32, 3: 4} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -446,7 +446,7 @@ result: unknown { Source: {1: x.single_int32, x.single_int64: 4} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -461,7 +461,7 @@ result: unknown { Source: [1, x.single_int32, 3, 4] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -475,7 +475,7 @@ result: unknown { Source: [1, x.single_int32, x.single_int64, 4] declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -490,7 +490,7 @@ result: unknown { Source: TestAllTypes{single_int32: x.single_int32}.single_int32 == 2 declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool @@ -504,7 +504,7 @@ result: unknown { Source: TestAllTypes{single_int32: x.single_int32, single_int64: x.single_int64} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } declare f { function f int.(int) -> bool diff --git a/runtime/src/test/resources/wrappers.baseline b/runtime/src/test/resources/wrappers.baseline index 3305bbde4..718130bde 100644 --- a/runtime/src/test/resources/wrappers.baseline +++ b/runtime/src/test/resources/wrappers.baseline @@ -1,6 +1,6 @@ Source: x.single_bool_wrapper == true && x.single_bytes_wrapper == b'hi' && x.single_double_wrapper == -3.0 && x.single_float_wrapper == 1.5 && x.single_int32_wrapper == -12 && x.single_int64_wrapper == -34 && x.single_string_wrapper == 'hello' && x.single_uint32_wrapper == 12u && x.single_uint64_wrapper == 34u declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_int64_wrapper { @@ -35,7 +35,7 @@ result: true Source: x.single_bool_wrapper == google.protobuf.BoolValue{} && x.single_bytes_wrapper == google.protobuf.BytesValue{value: b'hi'} && x.single_double_wrapper == google.protobuf.DoubleValue{value: -3.0} && x.single_float_wrapper == google.protobuf.FloatValue{value: 1.5} && x.single_int32_wrapper == google.protobuf.Int32Value{value: -12} && x.single_int64_wrapper == google.protobuf.Int64Value{value: -34} && x.single_string_wrapper == google.protobuf.StringValue{} && x.single_uint32_wrapper == google.protobuf.UInt32Value{value: 12u} && x.single_uint64_wrapper == google.protobuf.UInt64Value{value: 34u} declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=single_int64_wrapper { @@ -68,7 +68,7 @@ result: true Source: x.single_bool_wrapper == null && x.single_bytes_wrapper == null && x.single_double_wrapper == null && x.single_float_wrapper == null && x.single_int32_wrapper == null && x.single_int64_wrapper == null && x.single_string_wrapper == null && x.single_uint32_wrapper == null && x.single_uint64_wrapper == null declare x { - value dev.cel.testing.testdata.proto3.TestAllTypes + value google.api.expr.test.v1.proto3.TestAllTypes } =====> bindings: {x=} diff --git a/testing/src/main/java/dev/cel/testing/BUILD.bazel b/testing/src/main/java/dev/cel/testing/BUILD.bazel index 4643e1272..c708ad57f 100644 --- a/testing/src/main/java/dev/cel/testing/BUILD.bazel +++ b/testing/src/main/java/dev/cel/testing/BUILD.bazel @@ -153,11 +153,11 @@ java_library( "//common/internal:cel_descriptor_pools", "//common/internal:file_descriptor_converter", "//common/resources/testdata/proto3:standalone_global_enum_java_proto", - "//common/resources/testdata/proto3:test_all_types_java_proto", "//common/types:cel_types", "//runtime:interpreter", "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", + "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java_util", diff --git a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java index 811af7033..54fbe3382 100644 --- a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java +++ b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java @@ -23,6 +23,9 @@ import dev.cel.expr.Type; import dev.cel.expr.Type.AbstractType; import dev.cel.expr.UnknownSet; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.NestedEnum; +import com.google.api.expr.test.v1.proto3.TestAllTypesProto.TestAllTypes.NestedMessage; import com.google.common.base.Ascii; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -63,9 +66,6 @@ import dev.cel.runtime.Activation; import dev.cel.runtime.InterpreterException; import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes.NestedEnum; -import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes.NestedMessage; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -836,7 +836,7 @@ public void namespacedVariables() throws Exception { runTest(Activation.of("ns.x", 2)); container = "dev.cel.testing.testdata.proto3"; - Type messageType = CelTypes.createMessage("dev.cel.testing.testdata.proto3.TestAllTypes"); + Type messageType = CelTypes.createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("dev.cel.testing.testdata.proto3.msgVar", messageType); source = "msgVar.single_int32"; runTest( @@ -1767,14 +1767,14 @@ public void typeComparisons() throws Exception { source = "type(TestAllTypes{}) == TestAllTypes && " + "type(TestAllTypes{}) == proto3.TestAllTypes && " - + "type(TestAllTypes{}) == .dev.cel.testing.testdata.proto3.TestAllTypes && " + + "type(TestAllTypes{}) == .google.api.expr.test.v1.proto3.TestAllTypes && " + "type(proto3.TestAllTypes{}) == TestAllTypes && " + "type(proto3.TestAllTypes{}) == proto3.TestAllTypes && " - + "type(proto3.TestAllTypes{}) == .dev.cel.testing.testdata.proto3.TestAllTypes && " - + "type(.dev.cel.testing.testdata.proto3.TestAllTypes{}) == TestAllTypes && " - + "type(.dev.cel.testing.testdata.proto3.TestAllTypes{}) == proto3.TestAllTypes && " - + "type(.dev.cel.testing.testdata.proto3.TestAllTypes{}) == " - + ".dev.cel.testing.testdata.proto3.TestAllTypes"; + + "type(proto3.TestAllTypes{}) == .google.api.expr.test.v1.proto3.TestAllTypes && " + + "type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == TestAllTypes && " + + "type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == proto3.TestAllTypes && " + + "type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == " + + ".google.api.expr.test.v1.proto3.TestAllTypes"; runTest(Activation.EMPTY); // Test whether a type name is recognized as a type. @@ -1944,7 +1944,7 @@ public void dynamicMessage_adapted() throws Exception { .setSingleValue(Value.newBuilder().setStringValue("a")) .setSingleStruct( Struct.newBuilder().putFields("b", Value.newBuilder().setStringValue("c").build())) - .setSingleListValue( + .setListValue( ListValue.newBuilder().addValues(Value.newBuilder().setStringValue("d")).build()) .build(); @@ -2002,7 +2002,7 @@ public void dynamicMessage_adapted() throws Exception { source = "msg.single_struct"; assertThat(runTest(activation)).isInstanceOf(Map.class); - source = "msg.single_list_value"; + source = "msg.list_value"; assertThat(runTest(activation)).isInstanceOf(List.class); } From eb2e557231c322ebfe4f4f15ff85f26409478daa Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 22 Aug 2024 09:07:46 -0700 Subject: [PATCH 27/33] Add ListsExtension with flatten function (single level only) Recursive implementation will be added in the future. PiperOrigin-RevId: 666372924 --- .../main/java/dev/cel/extensions/BUILD.bazel | 16 +++ .../dev/cel/extensions/CelExtensions.java | 49 ++++++++- .../cel/extensions/CelListsExtensions.java | 101 ++++++++++++++++++ .../main/java/dev/cel/extensions/README.md | 30 ++++++ .../dev/cel/extensions/CelExtensionsTest.java | 3 +- .../extensions/CelListsExtensionsTest.java | 62 +++++++++++ 6 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java create mode 100644 extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel index b92bd9b54..7f6652666 100644 --- a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel @@ -16,6 +16,7 @@ java_library( deps = [ ":bindings", ":encoders", + ":lists", ":math", ":protos", ":sets", @@ -148,3 +149,18 @@ java_library( "@maven//:com_google_guava_guava", ], ) + +java_library( + name = "lists", + srcs = ["CelListsExtensions.java"], + tags = [ + ], + deps = [ + "//checker:checker_builder", + "//common:compiler_common", + "//common/types", + "//compiler:compiler_builder", + "//runtime", + "@maven//:com_google_guava_guava", + ], +) diff --git a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java index 353acdad3..eb795341e 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; import dev.cel.common.CelOptions; +import dev.cel.extensions.CelListsExtensions.Function; import java.util.Set; /** @@ -34,6 +35,7 @@ public final class CelExtensions { private static final CelProtoExtensions PROTO_EXTENSIONS = new CelProtoExtensions(); private static final CelBindingsExtensions BINDINGS_EXTENSIONS = new CelBindingsExtensions(); private static final CelEncoderExtensions ENCODER_EXTENSIONS = new CelEncoderExtensions(); + private static final CelListsExtensions LISTS_EXTENSIONS_ALL = new CelListsExtensions(); /** * Extended functions for string manipulation. @@ -187,9 +189,9 @@ public static CelSetsExtensions sets() { * *

Refer to README.md for available functions. * - *

This will include all functions denoted in {@link CelSetExtensions.Function}, including any - * future additions. To expose only a subset of functions, use {@link - * #sets(CelSetExtensions.Function...)} instead. + *

This will include all functions denoted in {@link CelSetsExtensions.Function}, including any + * future additions. To expose only a subset of functions, use {@link #sets(CelOptions, + * CelSetsExtensions.Function...)} instead. */ public static CelSetsExtensions sets(CelOptions celOptions) { return new CelSetsExtensions(celOptions); @@ -219,6 +221,43 @@ public static CelSetsExtensions sets( return new CelSetsExtensions(celOptions, functions); } + /** + * Extended functions for List manipulation. + * + *

Refer to README.md for available functions. + * + *

This will include only the specific functions denoted by {@link + * CelListsExtensions.Function}. + */ + public static CelListsExtensions lists() { + return LISTS_EXTENSIONS_ALL; + } + + /** + * Extended functions for List manipulation. + * + *

Refer to README.md for available functions. + * + *

This will include only the specific functions denoted by {@link + * CelListsExtensions.Function}. + */ + public static CelListsExtensions lists(CelListsExtensions.Function... functions) { + return lists(ImmutableSet.copyOf(functions)); + } + + /** + * Extended functions for List manipulation. + * + *

Refer to README.md for available functions. + * + *

This will include all functions denoted in {@link CelListsExtensions.Function}, including + * any future additions. To expose only a subset of functions, use {@link #lists(Function...)} + * instead. + */ + public static CelListsExtensions lists(Set functions) { + return new CelListsExtensions(functions); + } + /** * Retrieves all function names used by every extension libraries. * @@ -235,7 +274,9 @@ public static ImmutableSet getAllFunctionNames() { stream(CelSetsExtensions.Function.values()) .map(CelSetsExtensions.Function::getFunction), stream(CelEncoderExtensions.Function.values()) - .map(CelEncoderExtensions.Function::getFunction)) + .map(CelEncoderExtensions.Function::getFunction), + stream(CelListsExtensions.Function.values()) + .map(CelListsExtensions.Function::getFunction)) .collect(toImmutableSet()); } diff --git a/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java new file mode 100644 index 000000000..06eccd16b --- /dev/null +++ b/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java @@ -0,0 +1,101 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.extensions; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import dev.cel.checker.CelCheckerBuilder; +import dev.cel.common.CelFunctionDecl; +import dev.cel.common.CelOverloadDecl; +import dev.cel.common.types.ListType; +import dev.cel.common.types.TypeParamType; +import dev.cel.compiler.CelCompilerLibrary; +import dev.cel.runtime.CelRuntime; +import dev.cel.runtime.CelRuntime.CelFunctionBinding; +import dev.cel.runtime.CelRuntimeBuilder; +import dev.cel.runtime.CelRuntimeLibrary; +import java.util.Collection; +import java.util.Set; + +/** Internal implementation of CEL lists extensions. */ +final class CelListsExtensions implements CelCompilerLibrary, CelRuntimeLibrary { + + private static final TypeParamType LIST_PARAM_TYPE = TypeParamType.create("T"); + + @SuppressWarnings({"unchecked"}) // Unchecked: Type-checker guarantees casting safety. + public enum Function { + FLATTEN( + CelFunctionDecl.newFunctionDeclaration( + "flatten", + CelOverloadDecl.newMemberOverload( + "list_flatten", + "Flattens a list by a single level", + ListType.create(LIST_PARAM_TYPE), + ListType.create(ListType.create(LIST_PARAM_TYPE)))), + // TODO: add list_flatten_list_int + CelRuntime.CelFunctionBinding.from( + "list_flatten", Collection.class, list -> flatten(list, 1))), + ; + + private final CelFunctionDecl functionDecl; + private final ImmutableSet functionBindings; + + String getFunction() { + return functionDecl.name(); + } + + Function(CelFunctionDecl functionDecl, CelRuntime.CelFunctionBinding... functionBindings) { + this.functionDecl = functionDecl; + this.functionBindings = ImmutableSet.copyOf(functionBindings); + } + } + + private final ImmutableSet functions; + + CelListsExtensions() { + this.functions = ImmutableSet.copyOf(Function.values()); + } + + CelListsExtensions(Set functions) { + this.functions = ImmutableSet.copyOf(functions); + } + + @Override + public void setCheckerOptions(CelCheckerBuilder checkerBuilder) { + functions.forEach(function -> checkerBuilder.addFunctionDeclarations(function.functionDecl)); + } + + @Override + public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) { + functions.forEach(function -> runtimeBuilder.addFunctionBindings(function.functionBindings)); + } + + @SuppressWarnings("unchecked") + private static ImmutableList flatten(Collection list, int level) { + Preconditions.checkArgument(level == 1, "recursive flatten is not supported yet."); + ImmutableList.Builder builder = ImmutableList.builder(); + for (Object element : list) { + if (element instanceof Collection) { + Collection listItem = (Collection) element; + builder.addAll(listItem); + } else { + builder.add(element); + } + } + + return builder.build(); + } +} diff --git a/extensions/src/main/java/dev/cel/extensions/README.md b/extensions/src/main/java/dev/cel/extensions/README.md index 1163f334c..e99e6a93f 100644 --- a/extensions/src/main/java/dev/cel/extensions/README.md +++ b/extensions/src/main/java/dev/cel/extensions/README.md @@ -406,3 +406,33 @@ sets.intersects([1], [1, 2]) // true sets.intersects([[1], [2, 3]], [[1, 2], [2, 3.0]]) // true ``` +## Lists + +Extended functions for list manipulation. As a general note, all indices are +zero-based. + +### Flatten + +Flattens a list by one level. Support for flattening to a specified level +will be provided in the future. + +Examples: + +``` +[].flatten() // [] +[1,[2,3],[4]].flatten() // [1, 2, 3, 4] +[1,[2,[3,4]]].flatten() // [1, 2, [3, 4]] +[1,2,[],[],[3,4]].flatten() // [1, 2, 3, 4] +``` + +Note that due to the current limitations of type-checker, a compilation error +will occur if an already flat list is populated. For time being, you must wrap +the list in dyn if you anticipate having to deal with a flat list: + +``` +[1,2,3].flatten() // error +dyn([1,2,3]).flatten() // [1,2,3] +``` + +This will be addressed once we add the appropriate capabilities in the +type-checker to handle type-reductions, or union types. diff --git a/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java index d7b75f8dd..26c51b1f4 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java @@ -159,6 +159,7 @@ public void getAllFunctionNames() { "sets.equivalent", "sets.intersects", "base64.decode", - "base64.encode"); + "base64.encode", + "flatten"); } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java new file mode 100644 index 000000000..cee8de5b7 --- /dev/null +++ b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java @@ -0,0 +1,62 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.extensions; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.google.testing.junit.testparameterinjector.TestParameterInjector; +import com.google.testing.junit.testparameterinjector.TestParameters; +import dev.cel.bundle.Cel; +import dev.cel.bundle.CelFactory; +import dev.cel.common.CelValidationException; +import dev.cel.parser.CelStandardMacro; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(TestParameterInjector.class) +public class CelListsExtensionsTest { + private static final Cel CEL = + CelFactory.standardCelBuilder() + .setStandardMacros(CelStandardMacro.STANDARD_MACROS) + .addCompilerLibraries(CelExtensions.lists()) + .addRuntimeLibraries(CelExtensions.lists()) + .build(); + + @Test + @TestParameters("{expression: '[].flatten() == []'}") + @TestParameters("{expression: '[[1, 2]].flatten().exists(i, i == 1)'}") + @TestParameters("{expression: '[[], [[]], [[[]]]].flatten() == [[], [[]]]'}") + @TestParameters("{expression: '[1,[2,[3,4]]].flatten() == [1,2,[3,4]]'}") + @TestParameters("{expression: '[1,2,[],[],[3,4]].flatten() == [1,2,3,4]'}") + @TestParameters("{expression: '[1,[2,3],[[4,5]], [[[6,7]]]].flatten() == [1,2,3,[4,5],[[6,7]]]'}") + @TestParameters("{expression: 'dyn([1]).flatten() == [1]'}") + @TestParameters("{expression: 'dyn([{1: 2}]).flatten() == [{1: 2}]'}") + @TestParameters("{expression: 'dyn([1,2,3,4]).flatten() == [1,2,3,4]'}") + public void flattenSingleLevel_success(String expression) throws Exception { + boolean result = (boolean) CEL.createProgram(CEL.compile(expression).getAst()).eval(); + + assertThat(result).isTrue(); + } + + @Test + @TestParameters("{expression: '[1].flatten()'}") + @TestParameters("{expression: '[{1: 2}].flatten()'}") + @TestParameters("{expression: '[1,2,3,4].flatten()'}") + public void flattenSingleLevel_listIsSingleLevel_throws(String expression) { + // Note: Java lacks the capability of conditionally disabling type guards + // due to the lack of full-fledged dynamic dispatch. + assertThrows(CelValidationException.class, () -> CEL.compile(expression).getAst()); + } +} From dae82c6d10114bb1da643203569f90a757c6c5e6 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 22 Aug 2024 09:34:38 -0700 Subject: [PATCH 28/33] Enable retainComprehensionStructure by default PiperOrigin-RevId: 666382519 --- .../cel/optimizer/optimizers/SubexpressionOptimizer.java | 6 +++--- .../optimizers/SubexpressionOptimizerBaselineTest.java | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java index 293481d8f..ff3162cf4 100644 --- a/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java +++ b/optimizer/src/main/java/dev/cel/optimizer/optimizers/SubexpressionOptimizer.java @@ -744,8 +744,8 @@ public abstract static class Builder { * + @index0.map(@it0, [@it0 + @it0, @it0 + @it0]))} * * - * If targeting CEL-Java for the runtime, the recommended setting is to - * leave this disabled for maximal optimization efficiency. + * If targeting CEL-Java for the runtime, the recommended setting is to leave this disabled + * for maximal optimization efficiency. */ public abstract Builder retainComprehensionStructure(boolean value); @@ -783,7 +783,7 @@ public static Builder newBuilder() { .iterationLimit(500) .populateMacroCalls(false) .enableCelBlock(false) - .retainComprehensionStructure(false) + .retainComprehensionStructure(true) .subexpressionMaxRecursionDepth(0); } diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index 9e67bda85..1f7de0a7e 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -259,6 +259,7 @@ public void large_expressions_block_recursion_depth_1() throws Exception { CEL, SubexpressionOptimizerOptions.newBuilder() .populateMacroCalls(true) + .retainComprehensionStructure(false) .enableCelBlock(true) .subexpressionMaxRecursionDepth(1) .build()); @@ -273,6 +274,7 @@ public void large_expressions_block_recursion_depth_2() throws Exception { CEL, SubexpressionOptimizerOptions.newBuilder() .populateMacroCalls(true) + .retainComprehensionStructure(false) .enableCelBlock(true) .subexpressionMaxRecursionDepth(2) .build()); @@ -287,6 +289,7 @@ public void large_expressions_block_recursion_depth_3() throws Exception { CEL, SubexpressionOptimizerOptions.newBuilder() .populateMacroCalls(true) + .retainComprehensionStructure(false) .enableCelBlock(true) .subexpressionMaxRecursionDepth(3) .build()); From 6c71f1602f23ea7f75020091d7091ede9ab3b03d Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 30 Aug 2024 09:06:47 -0700 Subject: [PATCH 29/33] Migrate interpreter tests to fluent APIs PiperOrigin-RevId: 669345287 --- .../src/main/java/dev/cel/runtime/BUILD.bazel | 1 + .../dev/cel/runtime/CelVariableResolver.java | 5 +- .../runtime/HierarchicalVariableResolver.java | 44 + .../src/test/java/dev/cel/runtime/BUILD.bazel | 8 +- .../cel/runtime/CelValueInterpreterTest.java | 54 +- .../java/dev/cel/runtime/InterpreterTest.java | 46 +- testing/BUILD.bazel | 15 - .../src/main/java/dev/cel/testing/BUILD.bazel | 60 +- .../dev/cel/testing/BaseInterpreterTest.java | 1362 +++++++++-------- .../dev/cel/testing/BaselineTestCase.java | 4 + .../src/main/java/dev/cel/testing/Eval.java | 44 - .../dev/cel/testing/EvalCelValueSync.java | 95 -- .../main/java/dev/cel/testing/EvalSync.java | 79 - .../src/test/java/dev/cel/testing/BUILD.bazel | 12 - .../java/dev/cel/testing/EvalSyncTest.java | 185 --- 15 files changed, 817 insertions(+), 1197 deletions(-) create mode 100644 runtime/src/main/java/dev/cel/runtime/HierarchicalVariableResolver.java delete mode 100644 testing/src/main/java/dev/cel/testing/Eval.java delete mode 100644 testing/src/main/java/dev/cel/testing/EvalCelValueSync.java delete mode 100644 testing/src/main/java/dev/cel/testing/EvalSync.java delete mode 100644 testing/src/test/java/dev/cel/testing/EvalSyncTest.java diff --git a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel index 20031fc22..109e13d97 100644 --- a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel @@ -135,6 +135,7 @@ RUNTIME_SOURCES = [ "CelRuntimeLegacyImpl.java", "CelRuntimeLibrary.java", "CelVariableResolver.java", + "HierarchicalVariableResolver.java", "UnknownContext.java", ] diff --git a/runtime/src/main/java/dev/cel/runtime/CelVariableResolver.java b/runtime/src/main/java/dev/cel/runtime/CelVariableResolver.java index ea5cfb4ac..76e6bc76e 100644 --- a/runtime/src/main/java/dev/cel/runtime/CelVariableResolver.java +++ b/runtime/src/main/java/dev/cel/runtime/CelVariableResolver.java @@ -50,9 +50,6 @@ public interface CelVariableResolver { */ static CelVariableResolver hierarchicalVariableResolver( CelVariableResolver primary, CelVariableResolver secondary) { - return (name) -> { - Optional value = primary.find(name); - return value.isPresent() ? value : secondary.find(name); - }; + return HierarchicalVariableResolver.newInstance(primary, secondary); } } diff --git a/runtime/src/main/java/dev/cel/runtime/HierarchicalVariableResolver.java b/runtime/src/main/java/dev/cel/runtime/HierarchicalVariableResolver.java new file mode 100644 index 000000000..5efc4fea4 --- /dev/null +++ b/runtime/src/main/java/dev/cel/runtime/HierarchicalVariableResolver.java @@ -0,0 +1,44 @@ +// Copyright 2024 Google LLC +// +// Licensed 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 +// +// https://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 dev.cel.runtime; + +import java.util.Optional; + +final class HierarchicalVariableResolver implements CelVariableResolver { + + private final CelVariableResolver primary; + private final CelVariableResolver secondary; + + @Override + public Optional find(String name) { + Optional value = primary.find(name); + return value.isPresent() ? value : secondary.find(name); + } + + @Override + public String toString() { + return secondary + " +> " + primary; + } + + static HierarchicalVariableResolver newInstance( + CelVariableResolver primary, CelVariableResolver secondary) { + return new HierarchicalVariableResolver(primary, secondary); + } + + private HierarchicalVariableResolver(CelVariableResolver primary, CelVariableResolver secondary) { + this.primary = primary; + this.secondary = secondary; + } +} diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel index 56e66137c..0cafcda6b 100644 --- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel @@ -62,11 +62,9 @@ java_library( ], deps = [ # "//java/com/google/testing/testsize:annotations", - "//common:options", "//testing:base_interpreter_test", - "//testing:eval", - "//testing:sync", "@maven//:junit_junit", + "@maven//:com_google_testparameterinjector_test_parameter_injector", ], ) @@ -78,11 +76,9 @@ java_library( ], deps = [ # "//java/com/google/testing/testsize:annotations", - "//common:options", "//testing:base_interpreter_test", - "//testing:cel_value_sync", - "//testing:eval", "@maven//:junit_junit", + "@maven//:com_google_testparameterinjector_test_parameter_injector", ], ) diff --git a/runtime/src/test/java/dev/cel/runtime/CelValueInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/CelValueInterpreterTest.java index 2ef7a250f..2a7de836d 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelValueInterpreterTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelValueInterpreterTest.java @@ -14,60 +14,20 @@ package dev.cel.runtime; +import com.google.testing.junit.testparameterinjector.TestParameter; +import com.google.testing.junit.testparameterinjector.TestParameterInjector; // import com.google.testing.testsize.MediumTest; -import dev.cel.common.CelOptions; import dev.cel.testing.BaseInterpreterTest; -import dev.cel.testing.Eval; -import dev.cel.testing.EvalCelValueSync; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; /** Tests for {@link Interpreter} and related functionality using {@code CelValue}. */ // @MediumTest -@RunWith(Parameterized.class) +@RunWith(TestParameterInjector.class) public class CelValueInterpreterTest extends BaseInterpreterTest { - private static final CelOptions SIGNED_UINT_TEST_OPTIONS = - CelOptions.current() - .enableTimestampEpoch(true) - .enableHeterogeneousNumericComparisons(true) - .enableCelValue(true) - .comprehensionMaxIterations(1_000) - .build(); - - public CelValueInterpreterTest(boolean declareWithCelType, Eval eval) { - super(declareWithCelType, eval); - } - - @Parameters - public static List testData() { - return new ArrayList<>( - Arrays.asList( - new Object[][] { - // SYNC_PROTO_TYPE - { - /* declareWithCelType= */ false, - new EvalCelValueSync(TEST_FILE_DESCRIPTORS, TEST_OPTIONS) - }, - // SYNC_PROTO_TYPE_SIGNED_UINT - { - /* declareWithCelType= */ false, - new EvalCelValueSync(TEST_FILE_DESCRIPTORS, SIGNED_UINT_TEST_OPTIONS) - }, - // SYNC_CEL_TYPE - { - /* declareWithCelType= */ true, - new EvalCelValueSync(TEST_FILE_DESCRIPTORS, TEST_OPTIONS) - }, - // SYNC_CEL_TYPE_SIGNED_UINT - { - /* declareWithCelType= */ true, - new EvalCelValueSync(TEST_FILE_DESCRIPTORS, SIGNED_UINT_TEST_OPTIONS) - }, - })); + public CelValueInterpreterTest(@TestParameter InterpreterTestOption testOption) { + super( + testOption.celOptions.toBuilder().enableCelValue(true).build(), + testOption.useNativeCelType); } } diff --git a/runtime/src/test/java/dev/cel/runtime/InterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/InterpreterTest.java index b59c16c28..1f8c18c22 100644 --- a/runtime/src/test/java/dev/cel/runtime/InterpreterTest.java +++ b/runtime/src/test/java/dev/cel/runtime/InterpreterTest.java @@ -14,54 +14,18 @@ package dev.cel.runtime; +import com.google.testing.junit.testparameterinjector.TestParameter; +import com.google.testing.junit.testparameterinjector.TestParameterInjector; // import com.google.testing.testsize.MediumTest; -import dev.cel.common.CelOptions; import dev.cel.testing.BaseInterpreterTest; -import dev.cel.testing.Eval; -import dev.cel.testing.EvalSync; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; /** Tests for {@link Interpreter} and related functionality. */ // @MediumTest -@RunWith(Parameterized.class) +@RunWith(TestParameterInjector.class) public class InterpreterTest extends BaseInterpreterTest { - private static final CelOptions SIGNED_UINT_TEST_OPTIONS = - CelOptions.current() - .enableTimestampEpoch(true) - .enableHeterogeneousNumericComparisons(true) - .comprehensionMaxIterations(1_000) - .build(); - - public InterpreterTest(boolean declareWithCelType, Eval eval) { - super(declareWithCelType, eval); - } - - @Parameters - public static List testData() { - - return new ArrayList<>( - Arrays.asList( - new Object[][] { - // SYNC_PROTO_TYPE - {/* declareWithCelType= */ false, new EvalSync(TEST_FILE_DESCRIPTORS, TEST_OPTIONS)}, - // SYNC_PROTO_TYPE_SIGNED_UINT - { - /* declareWithCelType= */ false, - new EvalSync(TEST_FILE_DESCRIPTORS, SIGNED_UINT_TEST_OPTIONS) - }, - // SYNC_CEL_TYPE - {/* declareWithCelType= */ true, new EvalSync(TEST_FILE_DESCRIPTORS, TEST_OPTIONS)}, - // SYNC_CEL_TYPE_SIGNED_UINT - { - /* declareWithCelType= */ true, - new EvalSync(TEST_FILE_DESCRIPTORS, SIGNED_UINT_TEST_OPTIONS) - }, - })); + public InterpreterTest(@TestParameter InterpreterTestOption testOption) { + super(testOption.celOptions, testOption.useNativeCelType); } } diff --git a/testing/BUILD.bazel b/testing/BUILD.bazel index bd958decc..1370356ba 100644 --- a/testing/BUILD.bazel +++ b/testing/BUILD.bazel @@ -29,21 +29,6 @@ java_library( exports = ["//testing/src/main/java/dev/cel/testing:cel_baseline_test_case"], ) -java_library( - name = "sync", - exports = ["//testing/src/main/java/dev/cel/testing:sync"], -) - -java_library( - name = "cel_value_sync", - exports = ["//testing/src/main/java/dev/cel/testing:cel_value_sync"], -) - -java_library( - name = "eval", - exports = ["//testing/src/main/java/dev/cel/testing:eval"], -) - java_library( name = "base_interpreter_test", exports = ["//testing/src/main/java/dev/cel/testing:base_interpreter_test"], diff --git a/testing/src/main/java/dev/cel/testing/BUILD.bazel b/testing/src/main/java/dev/cel/testing/BUILD.bazel index c708ad57f..5594c37be 100644 --- a/testing/src/main/java/dev/cel/testing/BUILD.bazel +++ b/testing/src/main/java/dev/cel/testing/BUILD.bazel @@ -81,60 +81,6 @@ java_library( ], ) -java_library( - name = "cel_value_sync", - testonly = 1, - srcs = ["EvalCelValueSync.java"], - deps = [ - ":eval", - "//common", - "//common:options", - "//common/internal:cel_descriptor_pools", - "//common/internal:default_message_factory", - "//common/internal:dynamic_proto", - "//common/internal:proto_message_factory", - "//common/values:cel_value_provider", - "//common/values:proto_message_value_provider", - "//runtime:interpreter", - "//runtime:runtime_type_provider_legacy", - "@@protobuf~//java/core", - "@maven//:com_google_guava_guava", - ], -) - -java_library( - name = "sync", - testonly = 1, - srcs = ["EvalSync.java"], - deps = [ - ":eval", - "//common", - "//common:options", - "//common/internal:cel_descriptor_pools", - "//common/internal:default_message_factory", - "//runtime:interpreter", - "@@protobuf~//java/core", - "@maven//:com_google_guava_guava", - ], -) - -java_library( - name = "eval", - testonly = 1, - srcs = [ - "Eval.java", - ], - deps = [ - "//common", - "//common:options", - "//runtime:base", - "//runtime:interpreter", - "@@protobuf~//java/core", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", - ], -) - java_library( name = "base_interpreter_test", testonly = 1, @@ -147,18 +93,18 @@ java_library( ], deps = [ ":cel_baseline_test_case", - ":eval", "//:java_truth", "//common", + "//common:options", "//common/internal:cel_descriptor_pools", "//common/internal:file_descriptor_converter", "//common/resources/testdata/proto3:standalone_global_enum_java_proto", "//common/types:cel_types", - "//runtime:interpreter", + "//runtime", + "//runtime:runtime_helper", "@@protobuf~//java/core", "@cel_spec//proto/cel/expr:expr_java_proto", "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto", - "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java_util", "@maven//:junit_junit", diff --git a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java index 54fbe3382..edcf5a260 100644 --- a/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java +++ b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java @@ -16,6 +16,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.truth.Truth.assertThat; +import static dev.cel.runtime.CelVariableResolver.hierarchicalVariableResolver; import static java.nio.charset.StandardCharsets.UTF_8; import dev.cel.expr.CheckedExpr; @@ -32,10 +33,10 @@ import com.google.common.collect.ImmutableSet; import com.google.common.io.Resources; import com.google.common.primitives.UnsignedLong; -import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.ByteString; +import com.google.protobuf.ByteString.ByteIterator; import com.google.protobuf.BytesValue; import com.google.protobuf.DescriptorProtos.FileDescriptorSet; import com.google.protobuf.Descriptors.Descriptor; @@ -47,6 +48,7 @@ import com.google.protobuf.Int32Value; import com.google.protobuf.Int64Value; import com.google.protobuf.ListValue; +import com.google.protobuf.Message; import com.google.protobuf.NullValue; import com.google.protobuf.StringValue; import com.google.protobuf.Struct; @@ -59,24 +61,55 @@ import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.Timestamps; import dev.cel.common.CelAbstractSyntaxTree; +import dev.cel.common.CelOptions; import dev.cel.common.CelProtoAbstractSyntaxTree; import dev.cel.common.internal.DefaultDescriptorPool; import dev.cel.common.internal.FileDescriptorSetConverter; import dev.cel.common.types.CelTypes; -import dev.cel.runtime.Activation; -import dev.cel.runtime.InterpreterException; +import dev.cel.runtime.CelEvaluationException; +import dev.cel.runtime.CelRuntime; +import dev.cel.runtime.CelRuntime.CelFunctionBinding; +import dev.cel.runtime.CelRuntimeFactory; +import dev.cel.runtime.CelVariableResolver; +import dev.cel.runtime.RuntimeHelpers; import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.LongStream; import org.junit.Test; /** Base class for evaluation outputs that can be stored and used as a baseline test. */ public abstract class BaseInterpreterTest extends CelBaselineTestCase { + private static CelOptions.Builder newBaseOptions() { + return CelOptions.current() + .enableTimestampEpoch(true) + .enableHeterogeneousNumericComparisons(true) + .enableOptionalSyntax(true) + .comprehensionMaxIterations(1_000); + } + + /** Test options to supply for interpreter tests. */ + protected enum InterpreterTestOption { + CEL_TYPE_SIGNED_UINT(newBaseOptions().enableUnsignedLongs(false).build(), true), + CEL_TYPE_UNSIGNED_UINT(newBaseOptions().enableUnsignedLongs(true).build(), true), + PROTO_TYPE_SIGNED_UINT(newBaseOptions().enableUnsignedLongs(false).build(), false), + PROTO_TYPE_UNSIGNED_UINT(newBaseOptions().enableUnsignedLongs(true).build(), false), + ; + + public final CelOptions celOptions; + public final boolean useNativeCelType; + + InterpreterTestOption(CelOptions celOptions, boolean useNativeCelType) { + this.celOptions = celOptions; + this.useNativeCelType = useNativeCelType; + } + } + protected static final Descriptor TEST_ALL_TYPE_DYNAMIC_DESCRIPTOR = getDeserializedTestAllTypeDescriptor(); @@ -86,187 +119,188 @@ public abstract class BaseInterpreterTest extends CelBaselineTestCase { StandaloneGlobalEnum.getDescriptor().getFile(), TEST_ALL_TYPE_DYNAMIC_DESCRIPTOR.getFile()); - private final Eval eval; + private final CelOptions celOptions; + private CelRuntime celRuntime; - private static Descriptor getDeserializedTestAllTypeDescriptor() { - try { - String fdsContent = readResourceContent("testdata/proto3/test_all_types.fds"); - FileDescriptorSet fds = TextFormat.parse(fdsContent, FileDescriptorSet.class); - ImmutableSet fileDescriptors = FileDescriptorSetConverter.convert(fds); + public BaseInterpreterTest(CelOptions celOptions, boolean useNativeCelType) { + super(useNativeCelType); + this.celOptions = celOptions; + this.celRuntime = + CelRuntimeFactory.standardCelRuntimeBuilder() + .addFileTypes(TEST_FILE_DESCRIPTORS) + .setOptions(celOptions) + .build(); + } - return fileDescriptors.stream() - .flatMap(f -> f.getMessageTypes().stream()) - .filter( - x -> - x.getFullName().equals("dev.cel.testing.testdata.serialized.proto3.TestAllTypes")) - .findAny() - .orElseThrow( - () -> - new IllegalStateException( - "Could not find deserialized TestAllTypes descriptor.")); - } catch (IOException e) { - throw new RuntimeException("Error loading TestAllTypes descriptor", e); + private CelAbstractSyntaxTree compileTestCase() { + CelAbstractSyntaxTree ast = prepareTest(TEST_FILE_DESCRIPTORS); + if (ast == null) { + return ast; } + assertAstRoundTrip(ast); + + return ast; + } + + private Object runTest() { + return runTest(ImmutableMap.of()); } - public BaseInterpreterTest(boolean declareWithCelType, Eval eval) { - super(declareWithCelType); - this.eval = eval; + private Object runTest(CelVariableResolver variableResolver) { + return runTestInternal(variableResolver); } /** Helper to run a test for configured instance variables. */ - @CanIgnoreReturnValue // Test generates a file to diff against baseline. Ignoring Intermediary - // evaluation is not a concern. - private Object runTest(Activation activation) throws Exception { - CelAbstractSyntaxTree ast = prepareTest(eval.fileDescriptors()); - if (ast == null) { - return null; - } - assertAstRoundTrip(ast); + private Object runTest(Map input) { + return runTestInternal(input); + } - testOutput().println("bindings: " + activation); + /** + * Helper to run a test for configured instance variables. Input must be of type map or {@link + * CelVariableResolver}. + */ + @SuppressWarnings("unchecked") + private Object runTestInternal(Object input) { + CelAbstractSyntaxTree ast = compileTestCase(); + printBinding(input); Object result = null; try { - result = eval.eval(ast, activation); + CelRuntime.Program program = celRuntime.createProgram(ast); + result = + input instanceof Map + ? program.eval(((Map) input)) + : program.eval((CelVariableResolver) input); if (result instanceof ByteString) { // Note: this call may fail for printing byte sequences that are not valid UTF-8, but works // pretty well for test purposes. result = ((ByteString) result).toStringUtf8(); } - testOutput().println("result: " + result); - } catch (InterpreterException e) { - testOutput().println("error: " + e.getMessage()); - testOutput().println("error_code: " + e.getErrorCode()); + println("result: " + result); + } catch (CelEvaluationException e) { + println("error: " + e.getMessage()); + println("error_code: " + e.getErrorCode()); } - testOutput().println(); + println(""); return result; } - /** - * Checks that the CheckedExpr produced by CelCompiler is equal to the one reproduced by the - * native CelAbstractSyntaxTree - */ - private void assertAstRoundTrip(CelAbstractSyntaxTree ast) { - CheckedExpr checkedExpr = CelProtoAbstractSyntaxTree.fromCelAst(ast).toCheckedExpr(); - CelProtoAbstractSyntaxTree protoAst = CelProtoAbstractSyntaxTree.fromCelAst(ast); - assertThat(checkedExpr).isEqualTo(protoAst.toCheckedExpr()); - } - @Test - public void arithmInt64() throws Exception { + public void arithmInt64() { source = "1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1 && 1 == 1 && 2 != 1"; - runTest(Activation.EMPTY); + runTest(); declareVariable("x", CelTypes.INT64); source = "1 + 2 - x * 3 / x + (x % 3)"; - runTest(Activation.of("x", -5L)); + runTest(ImmutableMap.of("x", -5L)); declareVariable("y", CelTypes.DYN); source = "x + y == 1"; - runTest(Activation.of("x", -5L).extend(Activation.of("y", 6))); + runTest(extend(ImmutableMap.of("x", -5L), ImmutableMap.of("y", 6))); } @Test - public void arithmInt64_error() throws Exception { + public void arithmInt64_error() { source = "9223372036854775807 + 1"; - runTest(Activation.EMPTY); + runTest(); source = "-9223372036854775808 - 1"; - runTest(Activation.EMPTY); + runTest(); source = "-(-9223372036854775808)"; - runTest(Activation.EMPTY); + runTest(); source = "5000000000 * 5000000000"; - runTest(Activation.EMPTY); + runTest(); source = "(-9223372036854775808)/-1"; - runTest(Activation.EMPTY); + runTest(); source = "1 / 0"; - runTest(Activation.EMPTY); + runTest(); source = "1 % 0"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void arithmUInt64() throws Exception { + public void arithmUInt64() { source = "1u < 2u && 1u <= 1u && 2u > 1u && 1u >= 1u && 1u == 1u && 2u != 1u"; - runTest(Activation.EMPTY); + runTest(); - boolean useUnsignedLongs = eval.celOptions().enableUnsignedLongs(); + boolean useUnsignedLongs = celOptions.enableUnsignedLongs(); declareVariable("x", CelTypes.UINT64); source = "1u + 2u + x * 3u / x + (x % 3u)"; - runTest(Activation.of("x", useUnsignedLongs ? UnsignedLong.valueOf(5L) : 5L)); + runTest(ImmutableMap.of("x", useUnsignedLongs ? UnsignedLong.valueOf(5L) : 5L)); declareVariable("y", CelTypes.DYN); source = "x + y == 11u"; runTest( - Activation.of("x", useUnsignedLongs ? UnsignedLong.valueOf(5L) : 5L) - .extend(Activation.of("y", useUnsignedLongs ? UnsignedLong.valueOf(6L) : 6))); + extend( + ImmutableMap.of("x", useUnsignedLongs ? UnsignedLong.valueOf(5L) : 5L), + ImmutableMap.of("y", useUnsignedLongs ? UnsignedLong.valueOf(6L) : 6))); source = "x - y == 1u"; runTest( - Activation.of("x", useUnsignedLongs ? UnsignedLong.valueOf(6L) : 6L) - .extend(Activation.of("y", useUnsignedLongs ? UnsignedLong.valueOf(5) : 5))); + extend( + ImmutableMap.of("x", useUnsignedLongs ? UnsignedLong.valueOf(6L) : 6L), + ImmutableMap.of("y", useUnsignedLongs ? UnsignedLong.valueOf(5) : 5))); } @Test - public void arithmUInt64_error() throws Exception { + public void arithmUInt64_error() { source = "18446744073709551615u + 1u"; - runTest(Activation.EMPTY); + runTest(); source = "0u - 1u"; - runTest(Activation.EMPTY); + runTest(); source = "5000000000u * 5000000000u"; - runTest(Activation.EMPTY); + runTest(); source = "1u / 0u"; - runTest(Activation.EMPTY); + runTest(); source = "1u % 0u"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void arithmDouble() throws Exception { + public void arithmDouble() { source = "1.9 < 2.0 && 1.1 <= 1.1 && 2.0 > 1.9 && 1.1 >= 1.1 && 1.1 == 1.1 && 2.0 != 1.9"; - runTest(Activation.EMPTY); + runTest(); declareVariable("x", CelTypes.DOUBLE); source = "1.0 + 2.3 + x * 3.0 / x"; - runTest(Activation.of("x", 3.33)); + runTest(ImmutableMap.of("x", 3.33)); declareVariable("y", CelTypes.DYN); source = "x + y == 9.99"; - runTest(Activation.of("x", 3.33d).extend(Activation.of("y", 6.66))); + runTest(extend(ImmutableMap.of("x", 3.33d), ImmutableMap.of("y", 6.66))); } @Test - public void quantifiers() throws Exception { + public void quantifiers() { source = "[1,-2,3].exists_one(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); source = "[-1,-2,3].exists_one(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); source = "[-1,-2,-3].exists(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); source = "[1,-2,3].exists(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); source = "[1,-2,3].all(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); source = "[1,2,3].all(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void arithmTimestamp() throws Exception { + public void arithmTimestamp() { container = Type.getDescriptor().getFile().getPackage(); declareVariable("ts1", CelTypes.TIMESTAMP); declareVariable("ts2", CelTypes.TIMESTAMP); @@ -274,24 +308,26 @@ public void arithmTimestamp() throws Exception { Duration d1 = Duration.newBuilder().setSeconds(15).setNanos(25).build(); Timestamp ts1 = Timestamp.newBuilder().setSeconds(25).setNanos(35).build(); Timestamp ts2 = Timestamp.newBuilder().setSeconds(10).setNanos(10).build(); - Activation activation = - Activation.of("d1", d1).extend(Activation.of("ts1", ts1)).extend(Activation.of("ts2", ts2)); + CelVariableResolver resolver = + extend( + extend(ImmutableMap.of("d1", d1), ImmutableMap.of("ts1", ts1)), + ImmutableMap.of("ts2", ts2)); source = "ts1 - ts2 == d1"; - runTest(activation); + runTest(resolver); source = "ts1 - d1 == ts2"; - runTest(activation); + runTest(resolver); source = "ts2 + d1 == ts1"; - runTest(activation); + runTest(resolver); source = "d1 + ts2 == ts1"; - runTest(activation); + runTest(resolver); } @Test - public void arithmDuration() throws Exception { + public void arithmDuration() { container = Type.getDescriptor().getFile().getPackage(); declareVariable("d1", CelTypes.DURATION); declareVariable("d2", CelTypes.DURATION); @@ -299,120 +335,123 @@ public void arithmDuration() throws Exception { Duration d1 = Duration.newBuilder().setSeconds(15).setNanos(25).build(); Duration d2 = Duration.newBuilder().setSeconds(10).setNanos(20).build(); Duration d3 = Duration.newBuilder().setSeconds(25).setNanos(45).build(); - Activation activation = - Activation.of("d1", d1).extend(Activation.of("d2", d2)).extend(Activation.of("d3", d3)); + + CelVariableResolver resolver = + extend( + extend(ImmutableMap.of("d1", d1), ImmutableMap.of("d2", d2)), + ImmutableMap.of("d3", d3)); source = "d1 + d2 == d3"; - runTest(activation); + runTest(resolver); source = "d3 - d1 == d2"; - runTest(activation); + runTest(resolver); } @Test - public void arithCrossNumericTypes() throws Exception { - if (!eval.celOptions().enableUnsignedLongs()) { + public void arithCrossNumericTypes() { + if (!celOptions.enableUnsignedLongs()) { skipBaselineVerification(); return; } source = "1.9 < 2 && 1 < 1.1 && 2u < 2.9 && 1.1 < 2u && 1 < 2u && 2u < 3"; - runTest(Activation.EMPTY); + runTest(); source = "1.9 <= 2 && 1 <= 1.1 && 2u <= 2.9 && 1.1 <= 2u && 2 <= 2u && 2u <= 2"; - runTest(Activation.EMPTY); + runTest(); source = "1.9 > 2 && 1 > 1.1 && 2u > 2.9 && 1.1 > 2u && 2 > 2u && 2u > 2"; - runTest(Activation.EMPTY); + runTest(); source = "1.9 >= 2 && 1 >= 1.1 && 2u >= 2.9 && 1.1 >= 2u && 2 >= 2u && 2u >= 2"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void booleans() throws Exception { + public void booleans() { declareVariable("x", CelTypes.BOOL); source = "x ? 1 : 0"; - runTest(Activation.of("x", true)); - runTest(Activation.of("x", false)); + runTest(ImmutableMap.of("x", true)); + runTest(ImmutableMap.of("x", false)); source = "(1 / 0 == 0 && false) == (false && 1 / 0 == 0)"; - runTest(Activation.EMPTY); + runTest(); source = "(1 / 0 == 0 || true) == (true || 1 / 0 == 0)"; - runTest(Activation.EMPTY); + runTest(); declareVariable("y", CelTypes.INT64); source = "1 / y == 1 || true"; - runTest(Activation.of("y", 0L)); + runTest(ImmutableMap.of("y", 0L)); source = "1 / y == 1 || false"; - runTest(Activation.of("y", 0L)); + runTest(ImmutableMap.of("y", 0L)); source = "false || 1 / y == 1"; - runTest(Activation.of("y", 0L)); + runTest(ImmutableMap.of("y", 0L)); source = "1 / y == 1 && true"; - runTest(Activation.of("y", 0L)); + runTest(ImmutableMap.of("y", 0L)); source = "true && 1 / y == 1"; - runTest(Activation.of("y", 0L)); + runTest(ImmutableMap.of("y", 0L)); source = "1 / y == 1 && false"; - runTest(Activation.of("y", 0L)); + runTest(ImmutableMap.of("y", 0L)); source = "(true > false) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(true > true) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(false > true) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(false > false) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(true >= false) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(true >= true) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(false >= false) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(false >= true) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(false < true) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(false < false) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(true < false) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(true < true) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(false <= true) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(false <= false) == true"; - runTest(Activation.EMPTY); + runTest(); source = "(true <= false) == false"; - runTest(Activation.EMPTY); + runTest(); source = "(true <= true) == true"; - runTest(Activation.EMPTY); + runTest(); } @Test public void strings() throws Exception { source = "'a' < 'b' && 'a' <= 'b' && 'b' > 'a' && 'a' >= 'a' && 'a' == 'a' && 'a' != 'b'"; - runTest(Activation.EMPTY); + runTest(); declareVariable("x", CelTypes.STRING); source = @@ -421,7 +460,7 @@ public void strings() throws Exception { + "x.startsWith('d') && " + "x.contains('de') && " + "!x.contains('abcdef')"; - runTest(Activation.of("x", "def")); + runTest(ImmutableMap.of("x", "def")); } @Test @@ -432,27 +471,27 @@ public void messages() throws Exception { .build(); declareVariable("x", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); source = "x.single_nested_message.bb == 43 && has(x.single_nested_message)"; - runTest(Activation.of("x", nestedMessage)); + runTest(ImmutableMap.of("x", nestedMessage)); declareVariable( "single_nested_message", CelTypes.createMessage(NestedMessage.getDescriptor().getFullName())); source = "single_nested_message.bb == 43"; - runTest(Activation.of("single_nested_message", nestedMessage.getSingleNestedMessage())); + runTest(ImmutableMap.of("single_nested_message", nestedMessage.getSingleNestedMessage())); source = "TestAllTypes{single_int64: 1, single_sfixed64: 2, single_int32: 2}.single_int32 == 2"; container = TestAllTypes.getDescriptor().getFile().getPackage(); - runTest(Activation.EMPTY); + runTest(); } @Test - public void messages_error() throws Exception { + public void messages_error() { source = "TestAllTypes{single_int32_wrapper: 12345678900}"; container = TestAllTypes.getDescriptor().getFile().getPackage(); - runTest(Activation.EMPTY); + runTest(); source = "TestAllTypes{}.map_string_string.a"; - runTest(Activation.EMPTY); + runTest(); } @Test @@ -478,7 +517,7 @@ public void has() throws Exception { + " && has(x.oneof_bool) && !has(x.oneof_type)" + " && has(x.map_int32_int64) && !has(x.map_string_string)" + " && has(x.single_nested_message) && !has(x.single_duration)"; - runTest(Activation.of("x", nestedMessage)); + runTest(ImmutableMap.of("x", nestedMessage)); } @Test @@ -491,32 +530,32 @@ public void duration() throws Exception { container = Type.getDescriptor().getFile().getPackage(); source = "d1 < d2"; - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1009))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d0910))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d1009).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d0910).extend(Activation.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1009))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d0910))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1009), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d0910), ImmutableMap.of("d2", d1010))); source = "d1 <= d2"; - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1009))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d0910))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d1009).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d0910).extend(Activation.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1009))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d0910))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1009), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d0910), ImmutableMap.of("d2", d1010))); source = "d1 > d2"; - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1009))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d0910))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d1009).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d0910).extend(Activation.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1009))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d0910))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1009), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d0910), ImmutableMap.of("d2", d1010))); source = "d1 >= d2"; - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1009))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d0910))); - runTest(Activation.of("d1", d1010).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d1009).extend(Activation.of("d2", d1010))); - runTest(Activation.of("d1", d0910).extend(Activation.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1009))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d0910))); + runTest(extend(ImmutableMap.of("d1", d1010), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d1009), ImmutableMap.of("d2", d1010))); + runTest(extend(ImmutableMap.of("d1", d0910), ImmutableMap.of("d2", d1010))); } @Test @@ -529,39 +568,38 @@ public void timestamp() throws Exception { container = Type.getDescriptor().getFile().getPackage(); source = "t1 < t2"; - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1009))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts0910))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts1009).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts0910).extend(Activation.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1009))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts0910))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1009), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts0910), ImmutableMap.of("t2", ts1010))); source = "t1 <= t2"; - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1009))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts0910))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts1009).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts0910).extend(Activation.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1009))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts0910))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1009), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts0910), ImmutableMap.of("t2", ts1010))); source = "t1 > t2"; - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1009))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts0910))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts1009).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts0910).extend(Activation.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1009))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts0910))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1009), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts0910), ImmutableMap.of("t2", ts1010))); source = "t1 >= t2"; - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1009))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts0910))); - runTest(Activation.of("t1", ts1010).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts1009).extend(Activation.of("t2", ts1010))); - runTest(Activation.of("t1", ts0910).extend(Activation.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1009))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts0910))); + runTest(extend(ImmutableMap.of("t1", ts1010), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts1009), ImmutableMap.of("t2", ts1010))); + runTest(extend(ImmutableMap.of("t1", ts0910), ImmutableMap.of("t2", ts1010))); } @Test - // TODO: Support JSON type pack/unpack google.protobuf.Any. - public void packUnpackAny() throws Exception { + public void packUnpackAny() { // The use of long values results in the incorrect type being serialized for a uint value. - if (!eval.celOptions().enableUnsignedLongs()) { + if (!celOptions.enableUnsignedLongs()) { skipBaselineVerification(); return; } @@ -576,62 +614,60 @@ public void packUnpackAny() throws Exception { // unpack any source = "any == d"; - runTest(Activation.of("any", any).extend(Activation.of("d", duration))); + runTest(extend(ImmutableMap.of("any", any), ImmutableMap.of("d", duration))); source = "any == message.single_any"; - runTest(Activation.of("any", any).extend(Activation.of("message", message))); + runTest(extend(ImmutableMap.of("any", any), ImmutableMap.of("message", message))); source = "d == message.single_any"; - runTest(Activation.of("d", duration).extend(Activation.of("message", message))); + runTest(extend(ImmutableMap.of("d", duration), ImmutableMap.of("message", message))); source = "any.single_int64 == 1"; - runTest(Activation.of("any", TestAllTypes.newBuilder().setSingleInt64(1).build())); + runTest(ImmutableMap.of("any", TestAllTypes.newBuilder().setSingleInt64(1).build())); source = "any == 1"; - runTest(Activation.of("any", Any.pack(Int64Value.of(1)))); + runTest(ImmutableMap.of("any", Any.pack(Int64Value.of(1)))); source = "list[0] == message"; - runTest( - Activation.copyOf( - ImmutableMap.of("list", ImmutableList.of(Any.pack(message)), "message", message))); + runTest(ImmutableMap.of("list", ImmutableList.of(Any.pack(message)), "message", message)); // pack any source = "TestAllTypes{single_any: d}"; - runTest(Activation.of("d", duration)); + runTest(ImmutableMap.of("d", duration)); source = "TestAllTypes{single_any: message.single_int64}"; - runTest(Activation.of("message", TestAllTypes.newBuilder().setSingleInt64(-1).build())); + runTest(ImmutableMap.of("message", TestAllTypes.newBuilder().setSingleInt64(-1).build())); source = "TestAllTypes{single_any: message.single_uint64}"; - runTest(Activation.of("message", TestAllTypes.newBuilder().setSingleUint64(1).build())); + runTest(ImmutableMap.of("message", TestAllTypes.newBuilder().setSingleUint64(1).build())); source = "TestAllTypes{single_any: 1.0}"; - runTest(Activation.EMPTY); + runTest(); source = "TestAllTypes{single_any: true}"; - runTest(Activation.EMPTY); + runTest(); source = "TestAllTypes{single_any: \"happy\"}"; - runTest(Activation.EMPTY); + runTest(); source = "TestAllTypes{single_any: message.single_bytes}"; runTest( - Activation.of( + ImmutableMap.of( "message", TestAllTypes.newBuilder().setSingleBytes(ByteString.copyFromUtf8("happy")).build())); } @Test - public void nestedEnums() throws Exception { + public void nestedEnums() { TestAllTypes nestedEnum = TestAllTypes.newBuilder().setSingleNestedEnum(NestedEnum.BAR).build(); declareVariable("x", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); container = TestAllTypes.getDescriptor().getFile().getPackage(); source = "x.single_nested_enum == TestAllTypes.NestedEnum.BAR"; - runTest(Activation.of("x", nestedEnum)); + runTest(ImmutableMap.of("x", nestedEnum)); declareVariable("single_nested_enum", CelTypes.INT64); source = "single_nested_enum == TestAllTypes.NestedEnum.BAR"; - runTest(Activation.of("single_nested_enum", nestedEnum.getSingleNestedEnumValue())); + runTest(ImmutableMap.of("single_nested_enum", nestedEnum.getSingleNestedEnumValue())); source = "TestAllTypes{single_nested_enum : TestAllTypes.NestedEnum.BAR}.single_nested_enum == 1"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void globalEnums() throws Exception { + public void globalEnums() { declareVariable("x", CelTypes.INT64); source = "x == dev.cel.testing.testdata.proto3.StandaloneGlobalEnum.SGAR"; - runTest(Activation.of("x", StandaloneGlobalEnum.SGAR.getNumber())); + runTest(ImmutableMap.of("x", StandaloneGlobalEnum.SGAR.getNumber())); } @Test @@ -640,33 +676,33 @@ public void lists() throws Exception { declareVariable("y", CelTypes.INT64); container = TestAllTypes.getDescriptor().getFile().getPackage(); source = "([1, 2, 3] + x.repeated_int32)[3] == 4"; - runTest(Activation.of("x", TestAllTypes.newBuilder().addRepeatedInt32(4).build())); + runTest(ImmutableMap.of("x", TestAllTypes.newBuilder().addRepeatedInt32(4).build())); source = "!(y in [1, 2, 3]) && y in [4, 5, 6]"; - runTest(Activation.of("y", 4L)); + runTest(ImmutableMap.of("y", 4L)); source = "TestAllTypes{repeated_int32: [1,2]}.repeated_int32[1] == 2"; - runTest(Activation.EMPTY); + runTest(); source = "1 in TestAllTypes{repeated_int32: [1,2]}.repeated_int32"; - runTest(Activation.EMPTY); + runTest(); source = "!(4 in [1, 2, 3]) && 1 in [1, 2, 3]"; - runTest(Activation.EMPTY); + runTest(); declareVariable("list", CelTypes.createList(CelTypes.INT64)); source = "!(4 in list) && 1 in list"; - runTest(Activation.of("list", ImmutableList.of(1L, 2L, 3L))); + runTest(ImmutableMap.of("list", ImmutableList.of(1L, 2L, 3L))); source = "!(y in list)"; - runTest(Activation.copyOf(ImmutableMap.of("y", 4L, "list", ImmutableList.of(1L, 2L, 3L)))); + runTest(ImmutableMap.of("y", 4L, "list", ImmutableList.of(1L, 2L, 3L))); source = "y in list"; - runTest(Activation.copyOf(ImmutableMap.of("y", 1L, "list", ImmutableList.of(1L, 2L, 3L)))); + runTest(ImmutableMap.of("y", 1L, "list", ImmutableList.of(1L, 2L, 3L))); source = "list[3]"; - runTest(Activation.copyOf(ImmutableMap.of("y", 1L, "list", ImmutableList.of(1L, 2L, 3L)))); + runTest(ImmutableMap.of("y", 1L, "list", ImmutableList.of(1L, 2L, 3L))); } @Test @@ -674,68 +710,66 @@ public void maps() throws Exception { declareVariable("x", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); container = TestAllTypes.getDescriptor().getFile().getPackage(); source = "{1: 2, 3: 4}[3] == 4"; - runTest(Activation.EMPTY); + runTest(); // Constant key in constant map. source = "3 in {1: 2, 3: 4} && !(4 in {1: 2, 3: 4})"; - runTest(Activation.EMPTY); + runTest(); source = "x.map_int32_int64[22] == 23"; - runTest(Activation.of("x", TestAllTypes.newBuilder().putMapInt32Int64(22, 23).build())); + runTest(ImmutableMap.of("x", TestAllTypes.newBuilder().putMapInt32Int64(22, 23).build())); source = "TestAllTypes{map_int32_int64: {21: 22, 22: 23}}.map_int32_int64[22] == 23"; - runTest(Activation.EMPTY); + runTest(); source = "TestAllTypes{oneof_type: NestedTestAllTypes{payload: x}}" + ".oneof_type.payload.map_int32_int64[22] == 23"; - runTest(Activation.of("x", TestAllTypes.newBuilder().putMapInt32Int64(22, 23).build())); + runTest(ImmutableMap.of("x", TestAllTypes.newBuilder().putMapInt32Int64(22, 23).build())); declareVariable("y", CelTypes.INT64); declareVariable("map", CelTypes.createMap(CelTypes.INT64, CelTypes.INT64)); // Constant key in variable map. source = "!(4 in map) && 1 in map"; - runTest(Activation.of("map", ImmutableMap.of(1L, 4L, 2L, 3L, 3L, 2L))); + runTest(ImmutableMap.of("map", ImmutableMap.of(1L, 4L, 2L, 3L, 3L, 2L))); // Variable key in constant map. source = "!(y in {1: 4, 2: 3, 3: 2}) && y in {5: 3, 4: 2, 3: 3}"; - runTest(Activation.of("y", 4L)); + runTest(ImmutableMap.of("y", 4L)); // Variable key in variable map. source = "!(y in map) && (y + 3) in map"; - runTest( - Activation.copyOf( - ImmutableMap.of("y", 1L, "map", ImmutableMap.of(4L, 1L, 5L, 2L, 6L, 3L)))); + runTest(ImmutableMap.of("y", 1L, "map", ImmutableMap.of(4L, 1L, 5L, 2L, 6L, 3L))); // Message value in map source = "TestAllTypes{map_int64_nested_type:{42:NestedTestAllTypes{payload:TestAllTypes{}}}}"; - runTest(Activation.EMPTY); + runTest(); // Repeated key - constant source = "{true: 1, false: 2, true: 3}[true]"; - runTest(Activation.EMPTY); + runTest(); // Repeated key - expressions declareVariable("b", CelTypes.BOOL); source = "{b: 1, !b: 2, b: 3}[true]"; - runTest(Activation.of("b", true)); + runTest(ImmutableMap.of("b", true)); } @Test public void comprehension() throws Exception { source = "[0, 1, 2].map(x, x > 0, x + 1) == [2, 3]"; - runTest(Activation.EMPTY); + runTest(); source = "[0, 1, 2].exists(x, x > 0)"; - runTest(Activation.EMPTY); + runTest(); source = "[0, 1, 2].exists(x, x > 2)"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void abstractType() throws Exception { + public void abstractType() { Type typeParam = CelTypes.createTypeParam("T"); Type abstractType = Type.newBuilder() @@ -750,14 +784,6 @@ public void abstractType() throws Exception { ImmutableList.of(CelTypes.createList(typeParam)), ImmutableList.of("T"), abstractType)); - eval.registrar() - .add( - "vector", - ImmutableList.of(List.class), - (Object[] args) -> { - List list = (List) args[0]; - return list.toArray(new Object[0]); - }); // Declare a function to access element of a vector. declareFunction( "at", @@ -766,24 +792,32 @@ public void abstractType() throws Exception { ImmutableList.of(abstractType, CelTypes.INT64), ImmutableList.of("T"), typeParam)); - eval.registrar() - .add( + // Add function bindings for above + addFunctionBinding( + CelFunctionBinding.from( + "vector", + ImmutableList.of(List.class), + (Object[] args) -> { + List list = (List) args[0]; + return list.toArray(new Object[0]); + }), + CelFunctionBinding.from( "at", ImmutableList.of(Object[].class, Long.class), (Object[] args) -> { Object[] array = (Object[]) args[0]; return array[(int) (long) args[1]]; - }); + })); source = "vector([1,2,3]).at(1) == 2"; - runTest(Activation.EMPTY); + runTest(); source = "vector([1,2,3]).at(1) + vector([7]).at(0)"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void namespacedFunctions() throws Exception { + public void namespacedFunctions() { declareFunction( "ns.func", globalOverload("ns_func_overload", ImmutableList.of(CelTypes.STRING), CelTypes.INT64)); @@ -793,60 +827,61 @@ public void namespacedFunctions() throws Exception { "ns_member_overload", ImmutableList.of(CelTypes.INT64, CelTypes.INT64), CelTypes.INT64)); - eval.registrar().add("ns_func_overload", String.class, s -> (long) s.length()); - eval.registrar().add("ns_member_overload", Long.class, Long.class, Long::sum); + addFunctionBinding( + CelFunctionBinding.from("ns_func_overload", String.class, s -> (long) s.length()), + CelFunctionBinding.from("ns_member_overload", Long.class, Long.class, Long::sum)); source = "ns.func('hello')"; - runTest(Activation.EMPTY); + runTest(); source = "ns.func('hello').member(ns.func('test'))"; - runTest(Activation.EMPTY); + runTest(); source = "{ns.func('test'): 2}"; - runTest(Activation.EMPTY); + runTest(); source = "{2: ns.func('test')}"; - runTest(Activation.EMPTY); + runTest(); source = "[ns.func('test'), 2]"; - runTest(Activation.EMPTY); + runTest(); source = "[ns.func('test')].map(x, x * 2)"; - runTest(Activation.EMPTY); + runTest(); source = "[1, 2].map(x, x * ns.func('test'))"; - runTest(Activation.EMPTY); + runTest(); container = "ns"; // Call with the container set as the function's namespace source = "ns.func('hello')"; - runTest(Activation.EMPTY); + runTest(); source = "func('hello')"; - runTest(Activation.EMPTY); + runTest(); source = "func('hello').member(func('test'))"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void namespacedVariables() throws Exception { + public void namespacedVariables() { container = "ns"; declareVariable("ns.x", CelTypes.INT64); source = "x"; - runTest(Activation.of("ns.x", 2)); + runTest(ImmutableMap.of("ns.x", 2)); container = "dev.cel.testing.testdata.proto3"; Type messageType = CelTypes.createMessage("google.api.expr.test.v1.proto3.TestAllTypes"); declareVariable("dev.cel.testing.testdata.proto3.msgVar", messageType); source = "msgVar.single_int32"; runTest( - Activation.of( + ImmutableMap.of( "dev.cel.testing.testdata.proto3.msgVar", TestAllTypes.newBuilder().setSingleInt32(5).build())); } @Test - public void durationFunctions() throws Exception { + public void durationFunctions() { declareVariable("d1", CelTypes.DURATION); Duration d1 = Duration.newBuilder().setSeconds(25 * 3600 + 59 * 60 + 1).setNanos(11000000).build(); @@ -855,196 +890,196 @@ public void durationFunctions() throws Exception { container = Type.getDescriptor().getFile().getPackage(); source = "d1.getHours()"; - runTest(Activation.of("d1", d1)); - runTest(Activation.of("d1", d2)); + runTest(ImmutableMap.of("d1", d1)); + runTest(ImmutableMap.of("d1", d2)); source = "d1.getMinutes()"; - runTest(Activation.of("d1", d1)); - runTest(Activation.of("d1", d2)); + runTest(ImmutableMap.of("d1", d1)); + runTest(ImmutableMap.of("d1", d2)); source = "d1.getSeconds()"; - runTest(Activation.of("d1", d1)); - runTest(Activation.of("d1", d2)); + runTest(ImmutableMap.of("d1", d1)); + runTest(ImmutableMap.of("d1", d2)); source = "d1.getMilliseconds()"; - runTest(Activation.of("d1", d1)); - runTest(Activation.of("d1", d2)); + runTest(ImmutableMap.of("d1", d1)); + runTest(ImmutableMap.of("d1", d2)); declareVariable("val", CelTypes.INT64); source = "d1.getHours() < val"; - runTest(Activation.of("d1", d1).extend(Activation.of("val", 30L))); + runTest(extend(ImmutableMap.of("d1", d1), ImmutableMap.of("val", 30L))); source = "d1.getMinutes() > val"; - runTest(Activation.of("d1", d1).extend(Activation.of("val", 30L))); + runTest(extend(ImmutableMap.of("d1", d1), ImmutableMap.of("val", 30L))); source = "d1.getSeconds() > val"; - runTest(Activation.of("d1", d1).extend(Activation.of("val", 30L))); + runTest(extend(ImmutableMap.of("d1", d1), ImmutableMap.of("val", 30L))); source = "d1.getMilliseconds() < val"; - runTest(Activation.of("d1", d1).extend(Activation.of("val", 30L))); + runTest(extend(ImmutableMap.of("d1", d1), ImmutableMap.of("val", 30L))); } @Test - public void timestampFunctions() throws Exception { + public void timestampFunctions() { declareVariable("ts1", CelTypes.TIMESTAMP); container = Type.getDescriptor().getFile().getPackage(); Timestamp ts1 = Timestamp.newBuilder().setSeconds(1).setNanos(11000000).build(); Timestamp ts2 = Timestamps.fromSeconds(-1); source = "ts1.getFullYear(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getFullYear()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getFullYear(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getFullYear(\"2:00\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMonth(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMonth()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getMonth(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMonth(\"-8:15\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDayOfYear(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDayOfYear()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getDayOfYear(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDayOfYear(\"-9:00\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDayOfMonth(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDayOfMonth()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getDayOfMonth(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDayOfMonth(\"8:00\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDate(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDate()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getDate(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getDate(\"9:30\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); Timestamp tsSunday = Timestamps.fromSeconds(3 * 24 * 3600); source = "ts1.getDayOfWeek(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", tsSunday)); + runTest(ImmutableMap.of("ts1", tsSunday)); source = "ts1.getDayOfWeek()"; - runTest(Activation.of("ts1", tsSunday)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", tsSunday)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getDayOfWeek(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", tsSunday)); + runTest(ImmutableMap.of("ts1", tsSunday)); source = "ts1.getDayOfWeek(\"-9:30\")"; - runTest(Activation.of("ts1", tsSunday)); + runTest(ImmutableMap.of("ts1", tsSunday)); source = "ts1.getHours(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getHours()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getHours(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getHours(\"6:30\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMinutes(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMinutes()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getMinutes(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMinutes(\"-8:00\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getSeconds(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getSeconds()"; - runTest(Activation.of("ts1", ts1)); - runTest(Activation.of("ts1", ts2)); + runTest(ImmutableMap.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts2)); source = "ts1.getSeconds(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getSeconds(\"-8:00\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMilliseconds(\"America/Los_Angeles\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMilliseconds()"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMilliseconds(\"Indian/Cocos\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); source = "ts1.getMilliseconds(\"-8:00\")"; - runTest(Activation.of("ts1", ts1)); + runTest(ImmutableMap.of("ts1", ts1)); declareVariable("val", CelTypes.INT64); source = "ts1.getFullYear() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 2013L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 2013L))); source = "ts1.getMonth() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 12L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 12L))); source = "ts1.getDayOfYear() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 13L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 13L))); source = "ts1.getDayOfMonth() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 10L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 10L))); source = "ts1.getDate() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 15L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 15L))); source = "ts1.getDayOfWeek() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 15L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 15L))); source = "ts1.getHours() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 15L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 15L))); source = "ts1.getMinutes() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 15L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 15L))); source = "ts1.getSeconds() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 15L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 15L))); source = "ts1.getMilliseconds() < val"; - runTest(Activation.of("ts1", ts1).extend(Activation.of("val", 15L))); + runTest(extend(ImmutableMap.of("ts1", ts1), ImmutableMap.of("val", 15L))); } @Test - public void unknownField() throws Exception { + public void unknownField() { container = TestAllTypes.getDescriptor().getFile().getPackage(); declareVariable("x", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); // Unknown field is accessed. source = "x.single_int32"; - runTest(Activation.EMPTY); + runTest(); source = "x.map_int32_int64[22]"; - runTest(Activation.EMPTY); + runTest(); source = "x.repeated_nested_message[1]"; - runTest(Activation.EMPTY); + runTest(); // Function call for an unknown field. source = "x.single_timestamp.getSeconds()"; - runTest(Activation.EMPTY); + runTest(); // Unknown field in a nested message source = "x.single_nested_message.bb"; - runTest(Activation.EMPTY); + runTest(); // Unknown field access in a map. source = "{1: x.single_int32}"; - runTest(Activation.EMPTY); + runTest(); // Unknown field access in a list. source = "[1, x.single_int32]"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void unknownResultSet() throws Exception { + public void unknownResultSet() { container = TestAllTypes.getDescriptor().getFile().getPackage(); declareVariable("x", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); TestAllTypes message = @@ -1055,505 +1090,505 @@ public void unknownResultSet() throws Exception { // unknown && true ==> unknown source = "x.single_int32 == 1 && true"; - runTest(Activation.EMPTY); + runTest(); // unknown && false ==> false source = "x.single_int32 == 1 && false"; - runTest(Activation.EMPTY); + runTest(); // unknown && Unknown ==> UnknownSet source = "x.single_int32 == 1 && x.single_int64 == 1"; - runTest(Activation.EMPTY); + runTest(); // unknown && error ==> unknown source = "x.single_int32 == 1 && x.single_timestamp <= timestamp(\"bad timestamp string\")"; - runTest(Activation.EMPTY); + runTest(); // true && unknown ==> unknown source = "true && x.single_int32 == 1"; - runTest(Activation.EMPTY); + runTest(); // false && unknown ==> false source = "false && x.single_int32 == 1"; - runTest(Activation.EMPTY); + runTest(); // error && unknown ==> unknown source = "x.single_timestamp <= timestamp(\"bad timestamp string\") && x.single_int32 == 1"; - runTest(Activation.EMPTY); + runTest(); // error && error ==> error source = "x.single_timestamp <= timestamp(\"bad timestamp string\") " + "&& x.single_timestamp > timestamp(\"another bad timestamp string\")"; - runTest(Activation.EMPTY); + runTest(); // unknown || true ==> true source = "x.single_int32 == 1 || x.single_string == \"test\""; - runTest(Activation.EMPTY); + runTest(); // unknown || false ==> unknown source = "x.single_int32 == 1 || x.single_string != \"test\""; - runTest(Activation.EMPTY); + runTest(); // unknown || unknown ==> UnknownSet source = "x.single_int32 == 1 || x.single_int64 == 1"; - runTest(Activation.EMPTY); + runTest(); // unknown || error ==> unknown source = "x.single_int32 == 1 || x.single_timestamp <= timestamp(\"bad timestamp string\")"; - runTest(Activation.EMPTY); + runTest(); // true || unknown ==> true source = "true || x.single_int32 == 1"; - runTest(Activation.EMPTY); + runTest(); // false || unknown ==> unknown source = "false || x.single_int32 == 1"; - runTest(Activation.EMPTY); + runTest(); // error || unknown ==> unknown source = "x.single_timestamp <= timestamp(\"bad timestamp string\") || x.single_int32 == 1"; - runTest(Activation.EMPTY); + runTest(); // error || error ==> error source = "x.single_timestamp <= timestamp(\"bad timestamp string\") " + "|| x.single_timestamp > timestamp(\"another bad timestamp string\")"; - runTest(Activation.EMPTY); + runTest(); // dispatch test declareFunction( "f", memberOverload("f", Arrays.asList(CelTypes.INT64, CelTypes.INT64), CelTypes.BOOL)); - eval.registrar().add("f", Integer.class, Integer.class, Objects::equals); + addFunctionBinding(CelFunctionBinding.from("f", Integer.class, Integer.class, Objects::equals)); // dispatch: unknown.f(1) ==> unknown source = "x.single_int32.f(1)"; - runTest(Activation.EMPTY); + runTest(); // dispatch: 1.f(unknown) ==> unknown source = "1.f(x.single_int32)"; - runTest(Activation.EMPTY); + runTest(); // dispatch: unknown.f(unknown) ==> unknownSet source = "x.single_int64.f(x.single_int32)"; - runTest(Activation.EMPTY); + runTest(); // ident is null(x is unbound) ==> unknown source = "x"; - runTest(Activation.of("y", message)); + runTest(ImmutableMap.of("y", message)); // ident is unknown ==> unknown source = "x"; ExprValue unknownMessage = ExprValue.newBuilder().setUnknown(UnknownSet.getDefaultInstance()).build(); - runTest(Activation.of("x", unknownMessage)); + runTest(ImmutableMap.of("x", unknownMessage)); // comprehension test // iteRange is unknown => unknown source = "x.map_int32_int64.map(x, x > 0, x + 1)"; - runTest(Activation.EMPTY); + runTest(); // exists, loop condition encounters unknown => skip unknown and check other element source = "[0, 2, 4].exists(z, z == 2 || z == x.single_int32)"; - runTest(Activation.EMPTY); + runTest(); // exists, loop condition encounters unknown => skip unknown and check other element, no dupe id // in result source = "[0, 2, 4].exists(z, z == x.single_int32)"; - runTest(Activation.EMPTY); + runTest(); // exists_one, loop condition encounters unknown => collect all unknowns source = "[0, 2, 4].exists_one(z, z == 0 || (z == 2 && z == x.single_int32) " + "|| (z == 4 && z == x.single_int64))"; - runTest(Activation.EMPTY); + runTest(); // all, loop condition encounters unknown => skip unknown and check other element source = "[0, 2].all(z, z == 2 || z == x.single_int32)"; - runTest(Activation.EMPTY); + runTest(); // filter, loop condition encounters unknown => skip unknown and check other element source = "[0, 2, 4].filter(z, z == 0 || (z == 2 && z == x.single_int32) " + "|| (z == 4 && z == x.single_int64))"; - runTest(Activation.EMPTY); + runTest(); // map, loop condition encounters unknown => skip unknown and check other element source = "[0, 2, 4].map(z, z == 0 || (z == 2 && z == x.single_int32) " + "|| (z == 4 && z == x.single_int64))"; - runTest(Activation.EMPTY); + runTest(); // conditional test // unknown ? 1 : 2 ==> unknown source = "x.single_int32 == 1 ? 1 : 2"; - runTest(Activation.EMPTY); + runTest(); // true ? unknown : 2 ==> unknown source = "true ? x.single_int32 : 2"; - runTest(Activation.EMPTY); + runTest(); // true ? 1 : unknown ==> 1 source = "true ? 1 : x.single_int32"; - runTest(Activation.EMPTY); + runTest(); // false ? unknown : 2 ==> 2 source = "false ? x.single_int32 : 2"; - runTest(Activation.EMPTY); + runTest(); // false ? 1 : unknown ==> unknown source = "false ? 1 : x.single_int32"; - runTest(Activation.EMPTY); + runTest(); // unknown condition ? unknown : unknown ==> unknown condition source = "x.single_int64 == 1 ? x.single_int32 : x.single_int32"; - runTest(Activation.EMPTY); + runTest(); // map with unknown key => unknown source = "{x.single_int32: 2, 3: 4}"; - runTest(Activation.EMPTY); + runTest(); // map with unknown value => unknown source = "{1: x.single_int32, 3: 4}"; - runTest(Activation.EMPTY); + runTest(); // map with unknown key and value => unknownSet source = "{1: x.single_int32, x.single_int64: 4}"; - runTest(Activation.EMPTY); + runTest(); // list with unknown => unknown source = "[1, x.single_int32, 3, 4]"; - runTest(Activation.EMPTY); + runTest(); // list with multiple unknowns => unknownSet source = "[1, x.single_int32, x.single_int64, 4]"; - runTest(Activation.EMPTY); + runTest(); // message with unknown => unknown source = "TestAllTypes{single_int32: x.single_int32}.single_int32 == 2"; - runTest(Activation.EMPTY); + runTest(); // message with multiple unknowns => unknownSet source = "TestAllTypes{single_int32: x.single_int32, single_int64: x.single_int64}"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void timeConversions() throws Exception { + public void timeConversions() { container = Type.getDescriptor().getFile().getPackage(); declareVariable("t1", CelTypes.TIMESTAMP); source = "timestamp(\"1972-01-01T10:00:20.021-05:00\")"; - runTest(Activation.EMPTY); + runTest(); source = "timestamp(123)"; - runTest(Activation.EMPTY); + runTest(); source = "duration(\"15.11s\")"; - runTest(Activation.EMPTY); + runTest(); source = "int(t1) == 100"; - runTest(Activation.of("t1", Timestamps.fromSeconds(100))); + runTest(ImmutableMap.of("t1", Timestamps.fromSeconds(100))); source = "duration(\"1h2m3.4s\")"; - runTest(Activation.EMPTY); + runTest(); // Not supported. source = "duration('inf')"; - runTest(Activation.EMPTY); + runTest(); source = "duration(duration('15.0s'))"; // Identity - runTest(Activation.EMPTY); + runTest(); source = "timestamp(timestamp(123))"; // Identity - runTest(Activation.EMPTY); + runTest(); } @Test - public void sizeTests() throws Exception { + public void sizeTests() { container = Type.getDescriptor().getFile().getPackage(); declareVariable("str", CelTypes.STRING); declareVariable("b", CelTypes.BYTES); source = "size(b) == 5 && b.size() == 5"; - runTest(Activation.of("b", ByteString.copyFromUtf8("happy"))); + runTest(ImmutableMap.of("b", ByteString.copyFromUtf8("happy"))); source = "size(str) == 5 && str.size() == 5"; - runTest(Activation.of("str", "happy")); - runTest(Activation.of("str", "happ\uDBFF\uDFFC")); + runTest(ImmutableMap.of("str", "happy")); + runTest(ImmutableMap.of("str", "happ\uDBFF\uDFFC")); source = "size({1:14, 2:15}) == 2 && {1:14, 2:15}.size() == 2"; - runTest(Activation.EMPTY); + runTest(); source = "size([1,2,3]) == 3 && [1,2,3].size() == 3"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void nonstrictQuantifierTests() throws Exception { + public void nonstrictQuantifierTests() { // Plain tests. Everything is constant. source = "[0, 2, 4].exists(x, 4/x == 2 && 4/(4-x) == 2)"; - runTest(Activation.EMPTY); + runTest(); source = "![0, 2, 4].all(x, 4/x != 2 && 4/(4-x) != 2)"; - runTest(Activation.EMPTY); + runTest(); declareVariable("four", CelTypes.INT64); // Condition is dynamic. source = "[0, 2, 4].exists(x, four/x == 2 && four/(four-x) == 2)"; - runTest(Activation.of("four", 4L)); + runTest(ImmutableMap.of("four", 4L)); source = "![0, 2, 4].all(x, four/x != 2 && four/(four-x) != 2)"; - runTest(Activation.of("four", 4L)); + runTest(ImmutableMap.of("four", 4L)); // Both range and condition are dynamic. source = "[0, 2, four].exists(x, four/x == 2 && four/(four-x) == 2)"; - runTest(Activation.of("four", 4L)); + runTest(ImmutableMap.of("four", 4L)); source = "![0, 2, four].all(x, four/x != 2 && four/(four-x) != 2)"; - runTest(Activation.of("four", 4L)); + runTest(ImmutableMap.of("four", 4L)); } @Test - public void regexpMatchingTests() throws Exception { + public void regexpMatchingTests() { // Constant everything. source = "matches(\"alpha\", \"^al.*\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \"^.al.*\") == false"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \".*ha$\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \"^.*ha.$\") == false"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \"\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \"ph\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \"^ph\") == false"; - runTest(Activation.EMPTY); + runTest(); source = "matches(\"alpha\", \"ph$\") == false"; - runTest(Activation.EMPTY); + runTest(); // Constant everything, receiver-style. source = "\"alpha\".matches(\"^al.*\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\"^.al.*\") == false"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\".*ha$\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\".*ha.$\") == false"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\"\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\"ph\") == true"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\"^ph\") == false"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\"ph$\") == false"; - runTest(Activation.EMPTY); + runTest(); // Constant string. declareVariable("regexp", CelTypes.STRING); source = "matches(\"alpha\", regexp) == true"; - runTest(Activation.of("regexp", "^al.*")); + runTest(ImmutableMap.of("regexp", "^al.*")); source = "matches(\"alpha\", regexp) == false"; - runTest(Activation.of("regexp", "^.al.*")); + runTest(ImmutableMap.of("regexp", "^.al.*")); source = "matches(\"alpha\", regexp) == true"; - runTest(Activation.of("regexp", ".*ha$")); + runTest(ImmutableMap.of("regexp", ".*ha$")); source = "matches(\"alpha\", regexp) == false"; - runTest(Activation.of("regexp", ".*ha.$")); + runTest(ImmutableMap.of("regexp", ".*ha.$")); // Constant string, receiver-style. source = "\"alpha\".matches(regexp) == true"; - runTest(Activation.of("regexp", "^al.*")); + runTest(ImmutableMap.of("regexp", "^al.*")); source = "\"alpha\".matches(regexp) == false"; - runTest(Activation.of("regexp", "^.al.*")); + runTest(ImmutableMap.of("regexp", "^.al.*")); source = "\"alpha\".matches(regexp) == true"; - runTest(Activation.of("regexp", ".*ha$")); + runTest(ImmutableMap.of("regexp", ".*ha$")); source = "\"alpha\".matches(regexp) == false"; - runTest(Activation.of("regexp", ".*ha.$")); + runTest(ImmutableMap.of("regexp", ".*ha.$")); // Constant regexp. declareVariable("s", CelTypes.STRING); source = "matches(s, \"^al.*\") == true"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); source = "matches(s, \"^.al.*\") == false"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); source = "matches(s, \".*ha$\") == true"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); source = "matches(s, \"^.*ha.$\") == false"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); // Constant regexp, receiver-style. source = "s.matches(\"^al.*\") == true"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); source = "s.matches(\"^.al.*\") == false"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); source = "s.matches(\".*ha$\") == true"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); source = "s.matches(\"^.*ha.$\") == false"; - runTest(Activation.of("s", "alpha")); + runTest(ImmutableMap.of("s", "alpha")); // No constants. source = "matches(s, regexp) == true"; - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", "^al.*"))); - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", ".*ha$"))); + runTest(ImmutableMap.of("s", "alpha", "regexp", "^al.*")); + runTest(ImmutableMap.of("s", "alpha", "regexp", ".*ha$")); source = "matches(s, regexp) == false"; - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", "^.al.*"))); - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", ".*ha.$"))); + runTest(ImmutableMap.of("s", "alpha", "regexp", "^.al.*")); + runTest(ImmutableMap.of("s", "alpha", "regexp", ".*ha.$")); // No constants, receiver-style. source = "s.matches(regexp) == true"; - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", "^al.*"))); - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", ".*ha$"))); + runTest(ImmutableMap.of("s", "alpha", "regexp", "^al.*")); + runTest(ImmutableMap.of("s", "alpha", "regexp", ".*ha$")); source = "s.matches(regexp) == false"; - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", "^.al.*"))); - runTest(Activation.copyOf(ImmutableMap.of("s", "alpha", "regexp", ".*ha.$"))); + runTest(ImmutableMap.of("s", "alpha", "regexp", "^.al.*")); + runTest(ImmutableMap.of("s", "alpha", "regexp", ".*ha.$")); } @Test - public void regexpMatches_error() throws Exception { + public void regexpMatches_error() { source = "matches(\"alpha\", \"**\")"; - runTest(Activation.EMPTY); + runTest(); source = "\"alpha\".matches(\"**\")"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void int64Conversions() throws Exception { + public void int64Conversions() { source = "int('-1')"; // string converts to -1 - runTest(Activation.EMPTY); + runTest(); source = "int(2.1)"; // double converts to 2 - runTest(Activation.EMPTY); + runTest(); source = "int(18446744073709551615u)"; // 2^64-1 should error - runTest(Activation.EMPTY); + runTest(); source = "int(1e99)"; // out of range should error - runTest(Activation.EMPTY); + runTest(); source = "int(42u)"; // converts to 42 - runTest(Activation.EMPTY); + runTest(); } @Test - public void uint64Conversions() throws Exception { + public void uint64Conversions() { // The test case `uint(1e19)` succeeds with unsigned longs and fails with longs in a way that // cannot be easily tested. - if (!eval.celOptions().enableUnsignedLongs()) { + if (!celOptions.enableUnsignedLongs()) { skipBaselineVerification(); return; } source = "uint('1')"; // string converts to 1u - runTest(Activation.EMPTY); + runTest(); source = "uint(2.1)"; // double converts to 2u - runTest(Activation.EMPTY); + runTest(); source = "uint(-1)"; // should error - runTest(Activation.EMPTY); + runTest(); source = "uint(1e19)"; // valid uint but outside of int range - runTest(Activation.EMPTY); + runTest(); source = "uint(6.022e23)"; // outside uint range - runTest(Activation.EMPTY); + runTest(); source = "uint(42)"; // int converts to 42u - runTest(Activation.EMPTY); + runTest(); source = "uint('f1')"; // should error - runTest(Activation.EMPTY); + runTest(); source = "uint(1u)"; // identity - runTest(Activation.EMPTY); + runTest(); source = "uint(dyn(1u))"; // identity, check dynamic dispatch - runTest(Activation.EMPTY); + runTest(); } @Test - public void doubleConversions() throws Exception { + public void doubleConversions() { source = "double('1.1')"; // string converts to 1.1 - runTest(Activation.EMPTY); + runTest(); source = "double(2u)"; // uint converts to 2.0 - runTest(Activation.EMPTY); + runTest(); source = "double(-1)"; // int converts to -1.0 - runTest(Activation.EMPTY); + runTest(); source = "double('bad')"; - runTest(Activation.EMPTY); + runTest(); source = "double(1.5)"; // Identity - runTest(Activation.EMPTY); + runTest(); } @Test - public void stringConversions() throws Exception { + public void stringConversions() { source = "string(1.1)"; // double converts to '1.1' - runTest(Activation.EMPTY); + runTest(); source = "string(2u)"; // uint converts to '2' - runTest(Activation.EMPTY); + runTest(); source = "string(-1)"; // int converts to '-1' - runTest(Activation.EMPTY); + runTest(); // Byte literals in Google SQL only take the leading byte of an escape character. // This means that to translate a byte literal to a UTF-8 encoded string, all bytes must be // encoded in the literal as they would be laid out in memory for UTF-8, hence the extra octal // escape to achieve parity with the bidi test below. source = "string(b'abc\\303\\203')"; - runTest(Activation.EMPTY); // bytes convert to 'abcÃ' + runTest(); // bytes convert to 'abcÃ' // Bi-di conversion for strings and bytes for 'abcÃ', note the difference between the string // and byte literal values. source = "string(bytes('abc\\303'))"; - runTest(Activation.EMPTY); + runTest(); source = "string(timestamp('2009-02-13T23:31:30Z'))"; - runTest(Activation.EMPTY); + runTest(); source = "string(duration('1000000s'))"; - runTest(Activation.EMPTY); + runTest(); source = "string('hello')"; // Identity - runTest(Activation.EMPTY); + runTest(); } @Test @@ -1561,68 +1596,62 @@ public void bytes() throws Exception { source = "b'a' < b'b' && b'a' <= b'b' && b'b' > b'a' && b'a' >= b'a' && b'a' == b'a' && b'a' !=" + " b'b'"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void boolConversions() throws Exception { + public void boolConversions() { source = "bool(true)"; - runTest(Activation.EMPTY); // Identity + runTest(); // Identity source = "bool('true') && bool('TRUE') && bool('True') && bool('t') && bool('1')"; - runTest(Activation.EMPTY); // result is true + runTest(); // result is true source = "bool('false') || bool('FALSE') || bool('False') || bool('f') || bool('0')"; - runTest(Activation.EMPTY); // result is false + runTest(); // result is false source = "bool('TrUe')"; - runTest(Activation.EMPTY); // exception + runTest(); // exception source = "bool('FaLsE')"; - runTest(Activation.EMPTY); // exception + runTest(); // exception } @Test - public void bytesConversions() throws Exception { + public void bytesConversions() { source = "bytes('abc\\303')"; - runTest(Activation.EMPTY); // string converts to abcà in bytes form. + runTest(); // string converts to abcà in bytes form. source = "bytes(bytes('abc\\303'))"; // Identity - runTest(Activation.EMPTY); + runTest(); } @Test - public void dynConversions() throws Exception { + public void dynConversions() { source = "dyn(42)"; - runTest(Activation.EMPTY); + runTest(); source = "dyn({'a':1, 'b':2})"; - runTest(Activation.EMPTY); + runTest(); } @Test - public void dyn_error() throws Exception { + public void dyn_error() { source = "dyn('hello').invalid"; - runTest(Activation.EMPTY); + runTest(); source = "has(dyn('hello').invalid)"; - runTest(Activation.EMPTY); + runTest(); source = "dyn([]).invalid"; - runTest(Activation.EMPTY); + runTest(); source = "has(dyn([]).invalid)"; - runTest(Activation.EMPTY); + runTest(); } - // This lambda implements @Immutable interface 'Function', but 'InterpreterTest' has field 'eval' - // of type 'com.google.api.expr.cel.testing.Eval', the declaration of - // type - // 'com.google.api.expr.cel.testing.Eval' is not annotated with - // @com.google.errorprone.annotations.Immutable - @SuppressWarnings("Immutable") @Test - public void jsonValueTypes() throws Exception { + public void jsonValueTypes() { container = TestAllTypes.getDescriptor().getFile().getPackage(); declareVariable("x", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); @@ -1630,19 +1659,19 @@ public void jsonValueTypes() throws Exception { TestAllTypes xBool = TestAllTypes.newBuilder().setSingleValue(Value.newBuilder().setBoolValue(true)).build(); source = "x.single_value"; - runTest(Activation.of("x", xBool)); + runTest(ImmutableMap.of("x", xBool)); // JSON number selection with int comparison. TestAllTypes xInt = TestAllTypes.newBuilder().setSingleValue(Value.newBuilder().setNumberValue(1)).build(); source = "x.single_value == double(1)"; - runTest(Activation.of("x", xInt)); + runTest(ImmutableMap.of("x", xInt)); // JSON number selection with float comparison. TestAllTypes xFloat = TestAllTypes.newBuilder().setSingleValue(Value.newBuilder().setNumberValue(1.1)).build(); source = "x.single_value == 1.1"; - runTest(Activation.of("x", xFloat)); + runTest(ImmutableMap.of("x", xFloat)); // JSON null selection. TestAllTypes xNull = @@ -1650,7 +1679,7 @@ public void jsonValueTypes() throws Exception { .setSingleValue(Value.newBuilder().setNullValue(NullValue.NULL_VALUE)) .build(); source = "x.single_value == null"; - runTest(Activation.of("x", xNull)); + runTest(ImmutableMap.of("x", xNull)); // JSON string selection. TestAllTypes xString = @@ -1658,7 +1687,7 @@ public void jsonValueTypes() throws Exception { .setSingleValue(Value.newBuilder().setStringValue("hello")) .build(); source = "x.single_value == 'hello'"; - runTest(Activation.of("x", xString)); + runTest(ImmutableMap.of("x", xString)); // JSON list equality. TestAllTypes xList = @@ -1675,7 +1704,7 @@ public void jsonValueTypes() throws Exception { .addValues(Value.newBuilder().setNumberValue(-1.1)))) .build(); source = "x.single_value[0] == [['hello'], -1.1][0]"; - runTest(Activation.of("x", xList)); + runTest(ImmutableMap.of("x", xList)); // JSON struct equality. TestAllTypes xStruct = @@ -1692,7 +1721,7 @@ public void jsonValueTypes() throws Exception { .putFields("num", Value.newBuilder().setNumberValue(-1.1).build())) .build(); source = "x.single_struct.num == {'str': ['hello'], 'num': -1.1}['num']"; - runTest(Activation.of("x", xStruct)); + runTest(ImmutableMap.of("x", xStruct)); // Build a proto message using a dynamically constructed map and assign the map to a struct // value. @@ -1701,42 +1730,39 @@ public void jsonValueTypes() throws Exception { + "single_struct: " + "TestAllTypes{single_value: {'str': ['hello']}}.single_value" + "}"; - runTest(Activation.EMPTY); + runTest(); // Ensure that types are being wrapped and unwrapped on function dispatch. declareFunction( "pair", globalOverload("pair", ImmutableList.of(CelTypes.STRING, CelTypes.STRING), CelTypes.DYN)); - eval.registrar() - .add( + addFunctionBinding( + CelFunctionBinding.from( "pair", ImmutableList.of(String.class, String.class), (Object[] args) -> { String key = (String) args[0]; String val = (String) args[1]; - return eval.adapt( - Value.newBuilder() - .setStructValue( - Struct.newBuilder() - .putFields(key, Value.newBuilder().setStringValue(val).build())) - .build()); - }); + return Value.newBuilder() + .setStructValue( + Struct.newBuilder() + .putFields(key, Value.newBuilder().setStringValue(val).build())) + .build(); + })); source = "pair(x.single_struct.str[0], 'val')"; - runTest(Activation.of("x", xStruct)); + runTest(ImmutableMap.of("x", xStruct)); } @Test - public void jsonConversions() throws Exception { + public void jsonConversions() { declareVariable("ts", CelTypes.TIMESTAMP); declareVariable("du", CelTypes.DURATION); source = "google.protobuf.Struct { fields: {'timestamp': ts, 'duration': du } }"; - runTest( - Activation.copyOf( - ImmutableMap.of("ts", Timestamps.fromSeconds(100), "du", Durations.fromMillis(200)))); + runTest(ImmutableMap.of("ts", Timestamps.fromSeconds(100), "du", Durations.fromMillis(200))); } @Test - public void typeComparisons() throws Exception { + public void typeComparisons() { container = TestAllTypes.getDescriptor().getFile().getPackage(); // Test numeric types. @@ -1745,23 +1771,23 @@ public void typeComparisons() throws Exception { + "type(1u) != int && type(1) != uint && " + "type(uint(1.1)) == uint && " + "type(1.1) == double"; - runTest(Activation.EMPTY); + runTest(); // Test string and bytes types. source = "type('hello') == string && type(b'\277') == bytes"; - runTest(Activation.EMPTY); + runTest(); // Test list and map types. source = "type([1, 2, 3]) == list && type({'a': 1, 'b': 2}) == map"; - runTest(Activation.EMPTY); + runTest(); // Test bool types. source = "type(true) == bool && type(false) == bool"; - runTest(Activation.EMPTY); + runTest(); // Test well-known proto-based types. source = "type(duration('10s')) == google.protobuf.Duration"; - runTest(Activation.EMPTY); + runTest(); // Test external proto-based types with container resolution. source = @@ -1775,19 +1801,19 @@ public void typeComparisons() throws Exception { + "type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == proto3.TestAllTypes && " + "type(.google.api.expr.test.v1.proto3.TestAllTypes{}) == " + ".google.api.expr.test.v1.proto3.TestAllTypes"; - runTest(Activation.EMPTY); + runTest(); // Test whether a type name is recognized as a type. source = "type(TestAllTypes) == type"; - runTest(Activation.EMPTY); + runTest(); // Test whether the type resolution of a proto object is recognized as the message's type. source = "type(TestAllTypes{}) == TestAllTypes"; - runTest(Activation.EMPTY); + runTest(); // Test whether null resolves to null_type. source = "type(null) == null_type"; - runTest(Activation.EMPTY); + runTest(); } @Test @@ -1815,7 +1841,7 @@ public void wrappers() throws Exception { + "x.single_string_wrapper == 'hello' && " + "x.single_uint32_wrapper == 12u && " + "x.single_uint64_wrapper == 34u"; - runTest(Activation.of("x", wrapperBindings)); + runTest(ImmutableMap.of("x", wrapperBindings)); source = "x.single_bool_wrapper == google.protobuf.BoolValue{} && " @@ -1828,7 +1854,7 @@ public void wrappers() throws Exception { + "x.single_uint32_wrapper == google.protobuf.UInt32Value{value: 12u} && " + "x.single_uint64_wrapper == google.protobuf.UInt64Value{value: 34u}"; runTest( - Activation.of( + ImmutableMap.of( "x", wrapperBindings .setSingleBoolWrapper(BoolValue.getDefaultInstance()) @@ -1844,13 +1870,13 @@ public void wrappers() throws Exception { + "x.single_string_wrapper == null && " + "x.single_uint32_wrapper == null && " + "x.single_uint64_wrapper == null"; - runTest(Activation.of("x", TestAllTypes.getDefaultInstance())); + runTest(ImmutableMap.of("x", TestAllTypes.getDefaultInstance())); } @Test - public void longComprehension() throws Exception { + public void longComprehension() { ImmutableList l = LongStream.range(0L, 1000L).boxed().collect(toImmutableList()); - eval.registrar().add("constantLongList", ImmutableList.of(), args -> l); + addFunctionBinding(CelFunctionBinding.from("constantLongList", ImmutableList.of(), args -> l)); // Comprehension over compile-time constant long list. declareFunction( @@ -1858,19 +1884,20 @@ public void longComprehension() throws Exception { globalOverload( "constantLongList", ImmutableList.of(), CelTypes.createList(CelTypes.INT64))); source = "size(constantLongList().map(x, x+1)) == 1000"; - runTest(Activation.EMPTY); + runTest(); // Comprehension over long list that is not compile-time constant. declareVariable("longlist", CelTypes.createList(CelTypes.INT64)); source = "size(longlist.map(x, x+1)) == 1000"; - runTest(Activation.of("longlist", l)); + runTest(ImmutableMap.of("longlist", l)); // Comprehension over long list where the computation is very slow. // (This is here pro-forma only since in the synchronous interpreter there // is no notion of a computation being slow so that another computation can // build up a stack while waiting.) - eval.registrar().add("f_slow_inc", Long.class, n -> n + 1L); - eval.registrar().add("f_unleash", Object.class, x -> x); + addFunctionBinding( + CelFunctionBinding.from("f_slow_inc", Long.class, n -> n + 1L), + CelFunctionBinding.from("f_unleash", Object.class, x -> x)); declareFunction( "f_slow_inc", globalOverload("f_slow_inc", ImmutableList.of(CelTypes.INT64), CelTypes.INT64)); @@ -1882,15 +1909,11 @@ public void longComprehension() throws Exception { ImmutableList.of("A"), CelTypes.createTypeParam("A"))); source = "f_unleash(longlist.map(x, f_slow_inc(x)))[0] == 1"; - runTest(Activation.of("longlist", l)); + runTest(ImmutableMap.of("longlist", l)); } @Test - public void maxComprehension() throws Exception { - if (eval.celOptions().comprehensionMaxIterations() < 0) { - skipBaselineVerification(); - return; - } + public void maxComprehension() { // Comprehension over long list that is not compile-time constant. declareVariable("longlist", CelTypes.createList(CelTypes.INT64)); source = "size(longlist.map(x, x+1)) == 1000"; @@ -1898,31 +1921,31 @@ public void maxComprehension() throws Exception { // Comprehension which exceeds the configured iteration limit. ImmutableList tooLongList = LongStream.range(0L, COMPREHENSION_MAX_ITERATIONS + 1).boxed().collect(toImmutableList()); - runTest(Activation.of("longlist", tooLongList)); + runTest(ImmutableMap.of("longlist", tooLongList)); // Sequential iterations within the collective limit of 1000. source = "longlist.filter(i, i % 2 == 0).map(i, i * 2).map(i, i / 2).size() == 250"; ImmutableList l = LongStream.range(0L, COMPREHENSION_MAX_ITERATIONS / 2).boxed().collect(toImmutableList()); - runTest(Activation.of("longlist", l)); + runTest(ImmutableMap.of("longlist", l)); // Sequential iterations outside the limit of 1000. source = "(longlist + [0]).filter(i, i % 2 == 0).map(i, i * 2).map(i, i / 2).size() == 251"; - runTest(Activation.of("longlist", l)); + runTest(ImmutableMap.of("longlist", l)); // Nested iteration within the iteration limit. // Note, there is some double-counting of the inner-loops which causes the iteration limit to // get tripped sooner than one might expect for the nested case. source = "longlist.map(i, longlist.map(j, longlist.map(k, [i, j, k]))).size() == 9"; l = LongStream.range(0L, 9).boxed().collect(toImmutableList()); - runTest(Activation.of("longlist", l)); + runTest(ImmutableMap.of("longlist", l)); // Nested iteration which exceeds the iteration limit. This result may be surprising, but the // limit is tripped precisely because each complete iteration of an inner-loop counts as inner- // loop + 1 as there's not a clean way to deduct an iteration and only count the inner most // loop. l = LongStream.range(0L, 10).boxed().collect(toImmutableList()); - runTest(Activation.of("longlist", l)); + runTest(ImmutableMap.of("longlist", l)); } @Test @@ -1948,8 +1971,8 @@ public void dynamicMessage_adapted() throws Exception { ListValue.newBuilder().addValues(Value.newBuilder().setStringValue("d")).build()) .build(); - Activation activation = - Activation.of( + ImmutableMap input = + ImmutableMap.of( "msg", DynamicMessage.parseFrom( TestAllTypes.getDescriptor(), @@ -1959,51 +1982,51 @@ public void dynamicMessage_adapted() throws Exception { declareVariable("msg", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); source = "msg.single_any"; - assertThat(runTest(activation)).isInstanceOf(NestedMessage.class); + assertThat(runTest(input)).isInstanceOf(NestedMessage.class); source = "msg.single_bool_wrapper"; - assertThat(runTest(activation)).isInstanceOf(Boolean.class); + assertThat(runTest(input)).isInstanceOf(Boolean.class); source = "msg.single_bytes_wrapper"; - assertThat(runTest(activation)).isInstanceOf(String.class); + assertThat(runTest(input)).isInstanceOf(String.class); source = "msg.single_double_wrapper"; - assertThat(runTest(activation)).isInstanceOf(Double.class); + assertThat(runTest(input)).isInstanceOf(Double.class); source = "msg.single_float_wrapper"; - assertThat(runTest(activation)).isInstanceOf(Double.class); + assertThat(runTest(input)).isInstanceOf(Double.class); source = "msg.single_int32_wrapper"; - assertThat(runTest(activation)).isInstanceOf(Long.class); + assertThat(runTest(input)).isInstanceOf(Long.class); source = "msg.single_int64_wrapper"; - assertThat(runTest(activation)).isInstanceOf(Long.class); + assertThat(runTest(input)).isInstanceOf(Long.class); source = "msg.single_string_wrapper"; - assertThat(runTest(activation)).isInstanceOf(String.class); + assertThat(runTest(input)).isInstanceOf(String.class); source = "msg.single_uint32_wrapper"; - assertThat(runTest(activation)) - .isInstanceOf(eval.celOptions().enableUnsignedLongs() ? UnsignedLong.class : Long.class); + assertThat(runTest(input)) + .isInstanceOf(celOptions.enableUnsignedLongs() ? UnsignedLong.class : Long.class); source = "msg.single_uint64_wrapper"; - assertThat(runTest(activation)) - .isInstanceOf(eval.celOptions().enableUnsignedLongs() ? UnsignedLong.class : Long.class); + assertThat(runTest(input)) + .isInstanceOf(celOptions.enableUnsignedLongs() ? UnsignedLong.class : Long.class); source = "msg.single_duration"; - assertThat(runTest(activation)).isInstanceOf(Duration.class); + assertThat(runTest(input)).isInstanceOf(Duration.class); source = "msg.single_timestamp"; - assertThat(runTest(activation)).isInstanceOf(Timestamp.class); + assertThat(runTest(input)).isInstanceOf(Timestamp.class); source = "msg.single_value"; - assertThat(runTest(activation)).isInstanceOf(String.class); + assertThat(runTest(input)).isInstanceOf(String.class); source = "msg.single_struct"; - assertThat(runTest(activation)).isInstanceOf(Map.class); + assertThat(runTest(input)).isInstanceOf(Map.class); source = "msg.list_value"; - assertThat(runTest(activation)).isInstanceOf(List.class); + assertThat(runTest(input)).isInstanceOf(List.class); } @Test @@ -2011,65 +2034,65 @@ public void dynamicMessage_dynamicDescriptor() throws Exception { container = "dev.cel.testing.testdata.serialized.proto3"; source = "TestAllTypes {}"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(DynamicMessage.class); + assertThat(runTest()).isInstanceOf(DynamicMessage.class); source = "TestAllTypes { single_int32: 1, single_int64: 2, single_string: 'hello'}"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(DynamicMessage.class); + assertThat(runTest()).isInstanceOf(DynamicMessage.class); source = "TestAllTypes { single_int32: 1, single_int64: 2, single_string: 'hello'}.single_string"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(String.class); + assertThat(runTest()).isInstanceOf(String.class); // Test wrappers source = "TestAllTypes { single_int32_wrapper: 3 }.single_int32_wrapper"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Long.class); + assertThat(runTest()).isInstanceOf(Long.class); source = "TestAllTypes { single_int64_wrapper: 3 }.single_int64_wrapper"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Long.class); + assertThat(runTest()).isInstanceOf(Long.class); source = "TestAllTypes { single_bool_wrapper: true }.single_bool_wrapper"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Boolean.class); + assertThat(runTest()).isInstanceOf(Boolean.class); source = "TestAllTypes { single_bytes_wrapper: b'abc' }.single_bytes_wrapper"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(String.class); + assertThat(runTest()).isInstanceOf(String.class); source = "TestAllTypes { single_float_wrapper: 1.1 }.single_float_wrapper"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Double.class); + assertThat(runTest()).isInstanceOf(Double.class); source = "TestAllTypes { single_double_wrapper: 1.1 }.single_double_wrapper"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Double.class); + assertThat(runTest()).isInstanceOf(Double.class); source = "TestAllTypes { single_uint32_wrapper: 2u}.single_uint32_wrapper"; - assertThat(runTest(Activation.EMPTY)) - .isInstanceOf(eval.celOptions().enableUnsignedLongs() ? UnsignedLong.class : Long.class); + assertThat(runTest()) + .isInstanceOf(celOptions.enableUnsignedLongs() ? UnsignedLong.class : Long.class); source = "TestAllTypes { single_uint64_wrapper: 2u}.single_uint64_wrapper"; - assertThat(runTest(Activation.EMPTY)) - .isInstanceOf(eval.celOptions().enableUnsignedLongs() ? UnsignedLong.class : Long.class); + assertThat(runTest()) + .isInstanceOf(celOptions.enableUnsignedLongs() ? UnsignedLong.class : Long.class); source = "TestAllTypes { single_list_value: ['a', 1.5, true] }.single_list_value"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(List.class); + assertThat(runTest()).isInstanceOf(List.class); // Test nested messages source = "TestAllTypes { standalone_message: TestAllTypes.NestedMessage { } }.standalone_message"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(DynamicMessage.class); + assertThat(runTest()).isInstanceOf(DynamicMessage.class); source = "TestAllTypes { standalone_message: TestAllTypes.NestedMessage { bb: 5}" + " }.standalone_message.bb"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Long.class); + assertThat(runTest()).isInstanceOf(Long.class); source = "TestAllTypes { standalone_enum: TestAllTypes.NestedEnum.BAR }.standalone_enum"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Long.class); + assertThat(runTest()).isInstanceOf(Long.class); source = "TestAllTypes { map_string_string: {'key': 'value'}}"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(DynamicMessage.class); + assertThat(runTest()).isInstanceOf(DynamicMessage.class); source = "TestAllTypes { map_string_string: {'key': 'value'}}.map_string_string"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(Map.class); + assertThat(runTest()).isInstanceOf(Map.class); source = "TestAllTypes { map_string_string: {'key': 'value'}}.map_string_string['key']"; - assertThat(runTest(Activation.EMPTY)).isInstanceOf(String.class); + assertThat(runTest()).isInstanceOf(String.class); // Test any unpacking // With well-known type Any anyDuration = Any.pack(Durations.fromSeconds(100)); declareVariable("dur", CelTypes.TIMESTAMP); source = "TestAllTypes { single_any: dur }.single_any"; - assertThat(runTest(Activation.of("dur", anyDuration))).isInstanceOf(Duration.class); + assertThat(runTest(ImmutableMap.of("dur", anyDuration))).isInstanceOf(Duration.class); // with custom message clearAllDeclarations(); Any anyTestMsg = Any.pack(TestAllTypes.newBuilder().setSingleString("hello").build()); declareVariable( "any_packed_test_msg", CelTypes.createMessage(TestAllTypes.getDescriptor().getFullName())); source = "TestAllTypes { single_any: any_packed_test_msg }.single_any"; - assertThat(runTest(Activation.of("any_packed_test_msg", anyTestMsg))) + assertThat(runTest(ImmutableMap.of("any_packed_test_msg", anyTestMsg))) .isInstanceOf(TestAllTypes.class); // Test JSON map behavior @@ -2079,14 +2102,15 @@ public void dynamicMessage_dynamicDescriptor() throws Exception { DynamicMessage.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(TEST_ALL_TYPE_DYNAMIC_DESCRIPTOR); JsonFormat.parser().merge("{ 'map_string_string' : { 'foo' : 'bar' } }", dynamicMessageBuilder); - Activation activation = Activation.of("dynamic_msg", dynamicMessageBuilder.build()); + ImmutableMap input = + ImmutableMap.of("dynamic_msg", dynamicMessageBuilder.build()); source = "dynamic_msg"; - assertThat(runTest(activation)).isInstanceOf(DynamicMessage.class); + assertThat(runTest(input)).isInstanceOf(DynamicMessage.class); source = "dynamic_msg.map_string_string"; - assertThat(runTest(activation)).isInstanceOf(Map.class); + assertThat(runTest(input)).isInstanceOf(Map.class); source = "dynamic_msg.map_string_string['foo']"; - assertThat(runTest(activation)).isInstanceOf(String.class); + assertThat(runTest(input)).isInstanceOf(String.class); // Test function dispatch declareFunction( @@ -2100,21 +2124,135 @@ public void dynamicMessage_dynamicDescriptor() throws Exception { ImmutableList.of( CelTypes.createMessage(TEST_ALL_TYPE_DYNAMIC_DESCRIPTOR.getFullName())), CelTypes.BOOL)); - eval.registrar().add("f_msg_generated", TestAllTypes.class, x -> true); - eval.registrar().add("f_msg_dynamic", DynamicMessage.class, x -> true); - activation = - Activation.copyOf( - ImmutableMap.of( - "dynamic_msg", dynamicMessageBuilder.build(), - "test_msg", TestAllTypes.newBuilder().setSingleInt64(10L).build())); + addFunctionBinding( + CelFunctionBinding.from("f_msg_generated", TestAllTypes.class, x -> true), + CelFunctionBinding.from("f_msg_dynamic", DynamicMessage.class, x -> true)); + input = + ImmutableMap.of( + "dynamic_msg", dynamicMessageBuilder.build(), + "test_msg", TestAllTypes.newBuilder().setSingleInt64(10L).build()); source = "f_msg(dynamic_msg)"; - assertThat(runTest(activation)).isInstanceOf(Boolean.class); + assertThat(runTest(input)).isInstanceOf(Boolean.class); source = "f_msg(test_msg)"; - assertThat(runTest(activation)).isInstanceOf(Boolean.class); + assertThat(runTest(input)).isInstanceOf(Boolean.class); + } + + /** + * Checks that the CheckedExpr produced by CelCompiler is equal to the one reproduced by the + * native CelAbstractSyntaxTree + */ + private static void assertAstRoundTrip(CelAbstractSyntaxTree ast) { + CheckedExpr checkedExpr = CelProtoAbstractSyntaxTree.fromCelAst(ast).toCheckedExpr(); + CelProtoAbstractSyntaxTree protoAst = CelProtoAbstractSyntaxTree.fromCelAst(ast); + assertThat(checkedExpr).isEqualTo(protoAst.toCheckedExpr()); } private static String readResourceContent(String path) throws IOException { return Resources.toString(Resources.getResource(Ascii.toLowerCase(path)), UTF_8); } + + @SuppressWarnings("unchecked") + private void printBinding(Object input) { + if (input instanceof Map) { + Map inputMap = (Map) input; + if (inputMap.isEmpty()) { + println("bindings: {}"); + return; + } + + boolean first = true; + StringBuilder sb = new StringBuilder().append("{"); + for (Map.Entry entry : ((Map) input).entrySet()) { + if (!first) { + sb.append(", "); + } + first = false; + sb.append(entry.getKey()); + sb.append("="); + Object value = entry.getValue(); + if (value instanceof ByteString) { + sb.append(getHumanReadableString((ByteString) value)); + } else { + sb.append(entry.getValue()); + } + } + sb.append("}"); + println("bindings: " + sb); + } else { + println("bindings: " + input); + } + } + + private static String getHumanReadableString(ByteString byteString) { + // Very unfortunate we have to do this at all + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (ByteIterator i = byteString.iterator(); i.hasNext(); ) { + byte b = i.nextByte(); + sb.append(b); + if (i.hasNext()) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + + private static final class TestOnlyVariableResolver implements CelVariableResolver { + private final Map map; + + private static TestOnlyVariableResolver newInstance(Map map) { + return new TestOnlyVariableResolver(map); + } + + @Override + public Optional find(String name) { + return Optional.ofNullable(RuntimeHelpers.maybeAdaptPrimitive(map.get(name))); + } + + @Override + public String toString() { + return map.toString(); + } + + private TestOnlyVariableResolver(Map map) { + this.map = map; + } + } + + private static CelVariableResolver extend(Map primary, Map secondary) { + return hierarchicalVariableResolver( + TestOnlyVariableResolver.newInstance(primary), + TestOnlyVariableResolver.newInstance(secondary)); + } + + private static CelVariableResolver extend(CelVariableResolver primary, Map secondary) { + return hierarchicalVariableResolver(primary, TestOnlyVariableResolver.newInstance(secondary)); + } + + private void addFunctionBinding(CelRuntime.CelFunctionBinding... functionBindings) { + celRuntime = celRuntime.toRuntimeBuilder().addFunctionBindings(functionBindings).build(); + } + + private static Descriptor getDeserializedTestAllTypeDescriptor() { + try { + String fdsContent = readResourceContent("testdata/proto3/test_all_types.fds"); + FileDescriptorSet fds = TextFormat.parse(fdsContent, FileDescriptorSet.class); + ImmutableSet fileDescriptors = FileDescriptorSetConverter.convert(fds); + + return fileDescriptors.stream() + .flatMap(f -> f.getMessageTypes().stream()) + .filter( + x -> + x.getFullName().equals("dev.cel.testing.testdata.serialized.proto3.TestAllTypes")) + .findAny() + .orElseThrow( + () -> + new IllegalStateException( + "Could not find deserialized TestAllTypes descriptor.")); + } catch (IOException e) { + throw new RuntimeException("Error loading TestAllTypes descriptor", e); + } + } } diff --git a/testing/src/main/java/dev/cel/testing/BaselineTestCase.java b/testing/src/main/java/dev/cel/testing/BaselineTestCase.java index aa4215030..493106451 100644 --- a/testing/src/main/java/dev/cel/testing/BaselineTestCase.java +++ b/testing/src/main/java/dev/cel/testing/BaselineTestCase.java @@ -99,6 +99,10 @@ protected PrintWriter testOutput() { return writer; } + protected void println(String text) { + writer.println(text); + } + /** * A test watcher which calls baseline verification if the test succeeded. This is like @After, * but verification is only done if there haven't been other errors. diff --git a/testing/src/main/java/dev/cel/testing/Eval.java b/testing/src/main/java/dev/cel/testing/Eval.java deleted file mode 100644 index 2a2b4f5e8..000000000 --- a/testing/src/main/java/dev/cel/testing/Eval.java +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 dev.cel.testing; - -import com.google.common.collect.ImmutableList; -import com.google.errorprone.annotations.CheckReturnValue; -import com.google.protobuf.Descriptors.FileDescriptor; -import dev.cel.common.CelAbstractSyntaxTree; -import dev.cel.common.CelOptions; -import dev.cel.runtime.Activation; -import dev.cel.runtime.InterpreterException; -import dev.cel.runtime.Registrar; - -/** - * The {@code Eval} interface is used to model the core concerns of CEL evaluation during testing. - */ -@CheckReturnValue -public interface Eval { - /** Returns the set of file descriptors configured for evaluation. */ - ImmutableList fileDescriptors(); - - /** Returns the function / type registrar used during evaluation. */ - Registrar registrar(); - - CelOptions celOptions(); - - /** Adapts a Java POJO to a CEL value. */ - Object adapt(Object value) throws InterpreterException; - - /** Evaluates an {@code ast} against a set of inputs represented by the {@code Activation}. */ - Object eval(CelAbstractSyntaxTree ast, Activation activation) throws Exception; -} diff --git a/testing/src/main/java/dev/cel/testing/EvalCelValueSync.java b/testing/src/main/java/dev/cel/testing/EvalCelValueSync.java deleted file mode 100644 index 5b6a69bfa..000000000 --- a/testing/src/main/java/dev/cel/testing/EvalCelValueSync.java +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed 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 -// -// https://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 dev.cel.testing; - -import com.google.common.collect.ImmutableList; -import com.google.protobuf.Descriptors.FileDescriptor; -import dev.cel.common.CelAbstractSyntaxTree; -import dev.cel.common.CelDescriptorUtil; -import dev.cel.common.CelDescriptors; -import dev.cel.common.CelOptions; -import dev.cel.common.internal.DefaultDescriptorPool; -import dev.cel.common.internal.DefaultMessageFactory; -import dev.cel.common.internal.DynamicProto; -import dev.cel.common.internal.ProtoMessageFactory; -import dev.cel.common.values.CelValueProvider; -import dev.cel.common.values.ProtoMessageValueProvider; -import dev.cel.runtime.Activation; -import dev.cel.runtime.DefaultDispatcher; -import dev.cel.runtime.DefaultInterpreter; -import dev.cel.runtime.Interpreter; -import dev.cel.runtime.InterpreterException; -import dev.cel.runtime.Registrar; -import dev.cel.runtime.RuntimeTypeProvider; -import dev.cel.runtime.RuntimeTypeProviderLegacyImpl; - -/** - * The {@link EvalSync} class represents common concerns for synchronous evaluation using {@code - * CelValue}. - */ -public final class EvalCelValueSync implements Eval { - - private final ImmutableList fileDescriptors; - private final DefaultDispatcher dispatcher; - private final Interpreter interpreter; - private final RuntimeTypeProvider typeProvider; - private final CelOptions celOptions; - - public EvalCelValueSync(ImmutableList fileDescriptors, CelOptions celOptions) { - this.fileDescriptors = fileDescriptors; - this.dispatcher = DefaultDispatcher.create(celOptions); - this.celOptions = celOptions; - this.typeProvider = newTypeProvider(fileDescriptors); - this.interpreter = new DefaultInterpreter(typeProvider, dispatcher, celOptions); - } - - private RuntimeTypeProvider newTypeProvider(ImmutableList fileDescriptors) { - CelDescriptors celDescriptors = - CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(fileDescriptors); - DefaultDescriptorPool celDescriptorPool = DefaultDescriptorPool.create(celDescriptors); - ProtoMessageFactory messageFactory = DefaultMessageFactory.create(celDescriptorPool); - DynamicProto dynamicProto = DynamicProto.create(messageFactory); - CelValueProvider messageValueProvider = - ProtoMessageValueProvider.newInstance(dynamicProto, celOptions); - - return new RuntimeTypeProviderLegacyImpl( - celOptions, messageValueProvider, celDescriptorPool, dynamicProto); - } - - @Override - public ImmutableList fileDescriptors() { - return fileDescriptors; - } - - @Override - public Registrar registrar() { - return dispatcher; - } - - @Override - public CelOptions celOptions() { - return celOptions; - } - - @Override - public Object adapt(Object value) throws InterpreterException { - return typeProvider.adapt(value); - } - - @Override - public Object eval(CelAbstractSyntaxTree ast, Activation activation) throws Exception { - return interpreter.createInterpretable(ast).eval(activation); - } -} diff --git a/testing/src/main/java/dev/cel/testing/EvalSync.java b/testing/src/main/java/dev/cel/testing/EvalSync.java deleted file mode 100644 index 562043ce6..000000000 --- a/testing/src/main/java/dev/cel/testing/EvalSync.java +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 dev.cel.testing; - -import com.google.common.collect.ImmutableList; -import com.google.protobuf.Descriptors.FileDescriptor; -import dev.cel.common.CelAbstractSyntaxTree; -import dev.cel.common.CelDescriptorUtil; -import dev.cel.common.CelDescriptors; -import dev.cel.common.CelOptions; -import dev.cel.common.internal.DefaultDescriptorPool; -import dev.cel.common.internal.DefaultMessageFactory; -import dev.cel.runtime.Activation; -import dev.cel.runtime.DefaultDispatcher; -import dev.cel.runtime.DefaultInterpreter; -import dev.cel.runtime.DescriptorMessageProvider; -import dev.cel.runtime.Interpreter; -import dev.cel.runtime.InterpreterException; -import dev.cel.runtime.Registrar; -import dev.cel.runtime.RuntimeTypeProvider; - -/** The {@code EvalSync} class represents common concerns for synchronous evaluation. */ -public final class EvalSync implements Eval { - - private final ImmutableList fileDescriptors; - private final DefaultDispatcher dispatcher; - private final Interpreter interpreter; - private final RuntimeTypeProvider typeProvider; - private final CelOptions celOptions; - - public EvalSync(ImmutableList fileDescriptors, CelOptions celOptions) { - this.fileDescriptors = fileDescriptors; - this.dispatcher = DefaultDispatcher.create(celOptions); - CelDescriptors celDescriptors = - CelDescriptorUtil.getAllDescriptorsFromFileDescriptor(fileDescriptors); - this.typeProvider = - new DescriptorMessageProvider( - DefaultMessageFactory.create(DefaultDescriptorPool.create(celDescriptors)), celOptions); - this.interpreter = new DefaultInterpreter(typeProvider, dispatcher, celOptions); - this.celOptions = celOptions; - } - - @Override - public ImmutableList fileDescriptors() { - return fileDescriptors; - } - - @Override - public Registrar registrar() { - return dispatcher; - } - - @Override - public CelOptions celOptions() { - return celOptions; - } - - @Override - public Object adapt(Object value) throws InterpreterException { - return typeProvider.adapt(value); - } - - @Override - public Object eval(CelAbstractSyntaxTree ast, Activation activation) throws Exception { - return interpreter.createInterpretable(ast).eval(activation); - } -} diff --git a/testing/src/test/java/dev/cel/testing/BUILD.bazel b/testing/src/test/java/dev/cel/testing/BUILD.bazel index 6e4980c8a..90cf73e3a 100644 --- a/testing/src/test/java/dev/cel/testing/BUILD.bazel +++ b/testing/src/test/java/dev/cel/testing/BUILD.bazel @@ -10,19 +10,7 @@ java_library( srcs = glob(["*.java"]), deps = [ "//:java_truth", - "//common", - "//common:options", - "//common/types", - "//common/types:type_providers", - "//compiler", - "//compiler:compiler_builder", - "//parser:macro", - "//runtime:base", - "//runtime:interpreter", "//testing:line_differ", - "//testing:sync", - "@@protobuf~//java/core", - "@com_google_googleapis//google/type:type_java_proto", "@maven//:com_google_guava_guava", "@maven//:junit_junit", ], diff --git a/testing/src/test/java/dev/cel/testing/EvalSyncTest.java b/testing/src/test/java/dev/cel/testing/EvalSyncTest.java deleted file mode 100644 index 438ba0c43..000000000 --- a/testing/src/test/java/dev/cel/testing/EvalSyncTest.java +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed 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 -// -// https://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 dev.cel.testing; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableList; -import com.google.common.primitives.UnsignedLong; -import com.google.protobuf.Any; -import com.google.protobuf.BoolValue; -import com.google.protobuf.ByteString; -import com.google.protobuf.BytesValue; -import com.google.protobuf.Descriptors.FileDescriptor; -import com.google.protobuf.DoubleValue; -import com.google.protobuf.FloatValue; -import com.google.protobuf.Int32Value; -import com.google.protobuf.Int64Value; -import com.google.protobuf.Message; -import com.google.protobuf.StringValue; -import com.google.protobuf.UInt32Value; -import com.google.protobuf.UInt64Value; -import com.google.type.Expr; -import dev.cel.common.CelAbstractSyntaxTree; -import dev.cel.common.CelOptions; -import dev.cel.common.types.CelType; -import dev.cel.common.types.SimpleType; -import dev.cel.compiler.CelCompiler; -import dev.cel.compiler.CelCompilerFactory; -import dev.cel.parser.CelStandardMacro; -import dev.cel.runtime.Activation; -import dev.cel.runtime.InterpreterException; -import java.util.Arrays; -import java.util.List; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Enclosed.class) -public final class EvalSyncTest { - private static final ImmutableList TEST_FILE_DESCRIPTOR = - ImmutableList.of(Expr.getDescriptor().getFile()); - - private static final CelOptions TEST_OPTIONS = CelOptions.current().build(); - - private static final EvalSync EVAL = new EvalSync(TEST_FILE_DESCRIPTOR, TEST_OPTIONS); - - @RunWith(JUnit4.class) - public static class EvalSyncApiTests { - @Test - public void fileDescriptorsTest() { - assertThat(EVAL.fileDescriptors()).isEqualTo(TEST_FILE_DESCRIPTOR); - } - } - - @RunWith(Parameterized.class) - public static class ProtoTypeAdapterTests { - - @Parameters - public static List data() { - return Arrays.asList( - new Object[][] { - {BoolValue.of(true), true}, - {BoolValue.of(false), false}, - {DoubleValue.of(1.5D), 1.5D}, - {FloatValue.of(1.5f), 1.5D}, - {StringValue.of("test"), "test"}, - {Int32Value.of(1), 1L}, - {Int64Value.of(1), 1L}, - {UInt32Value.of(1), UnsignedLong.valueOf(1L)}, - {UInt64Value.of(1), UnsignedLong.valueOf(1L)}, - {BytesValue.of(ByteString.copyFromUtf8("test")), ByteString.copyFromUtf8("test")}, - }); - } - - private final Message protoMessage; - private final Object nativeValue; - - public ProtoTypeAdapterTests(Message protoMessage, Object nativeValue) { - this.protoMessage = protoMessage; - this.nativeValue = nativeValue; - } - - @Test - public void protoMessageAdapt_convertsToNativeValues() throws InterpreterException { - assertThat(EVAL.adapt(protoMessage)).isEqualTo(nativeValue); - assertThat(EVAL.adapt(Any.pack(protoMessage))).isEqualTo(nativeValue); - } - - @Test - public void nativeValueAdapt_doesNothing() throws InterpreterException { - assertThat(EVAL.adapt(nativeValue)).isEqualTo(nativeValue); - } - } - - /** - * Test cases to show that basic evaluation is working as intended. A comprehensive set of tests - * can be found in {@code BaseInterpreterTest}. - */ - @RunWith(Parameterized.class) - public static class EvalWithoutActivationTests { - private final String expr; - private final Object evaluatedResult; - - private static final CelCompiler COMPILER = - CelCompilerFactory.standardCelCompilerBuilder() - .setOptions(TEST_OPTIONS) - .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .build(); - - @Parameters - public static List data() { - return Arrays.asList( - new Object[][] { - {"1 < 2", true}, - {"1 + 2 + 3", 6L}, - {"1.9 + 2.0", 3.9}, - {"true == true", true}, - }); - } - - public EvalWithoutActivationTests(String expr, Object evaluatedResult) { - this.expr = expr; - this.evaluatedResult = evaluatedResult; - } - - @Test - public void evaluateExpr_returnsExpectedResult() throws Exception { - CelAbstractSyntaxTree ast = COMPILER.compile(expr).getAst(); - assertThat(EVAL.eval(ast, Activation.EMPTY)).isEqualTo(evaluatedResult); - } - } - - @RunWith(Parameterized.class) - public static class EvalWithActivationTests { - private final String expr; - private final Object paramValue; - private final Object evaluatedResult; - private final CelCompiler compiler; - - @Parameters - public static List data() { - return Arrays.asList( - new Object[][] { - {"x < 2", 1, SimpleType.INT, true}, - {"x + 2 + 3", 1, SimpleType.INT, 6L}, - {"x + 2.0", 1.9, SimpleType.DOUBLE, 3.9}, - {"x == true", true, SimpleType.BOOL, true}, - }); - } - - public EvalWithActivationTests( - String expr, Object paramValue, CelType paramType, Object evaluatedResult) { - this.expr = expr; - this.paramValue = paramValue; - this.evaluatedResult = evaluatedResult; - this.compiler = - CelCompilerFactory.standardCelCompilerBuilder() - .setOptions(TEST_OPTIONS) - .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .addVar("x", paramType) - .build(); - } - - @Test - public void expr_returnsExpectedResult() throws Exception { - CelAbstractSyntaxTree ast = compiler.compile(expr).getAst(); - assertThat(EVAL.eval(ast, Activation.of("x", paramValue))).isEqualTo(evaluatedResult); - } - } -} From 7398767f80578ae0b23f25d7484dde699b023544 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 30 Aug 2024 09:11:23 -0700 Subject: [PATCH 30/33] Provide an overload to accept a depth level in flatten function PiperOrigin-RevId: 669346696 --- .../cel/extensions/CelListsExtensions.java | 28 ++++++++++------- .../main/java/dev/cel/extensions/README.md | 22 +++++++++++--- .../extensions/CelListsExtensionsTest.java | 30 +++++++++++++++++++ 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java index 06eccd16b..55b5c723e 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java @@ -21,6 +21,7 @@ import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOverloadDecl; import dev.cel.common.types.ListType; +import dev.cel.common.types.SimpleType; import dev.cel.common.types.TypeParamType; import dev.cel.compiler.CelCompilerLibrary; import dev.cel.runtime.CelRuntime; @@ -44,11 +45,18 @@ public enum Function { "list_flatten", "Flattens a list by a single level", ListType.create(LIST_PARAM_TYPE), - ListType.create(ListType.create(LIST_PARAM_TYPE)))), - // TODO: add list_flatten_list_int + ListType.create(ListType.create(LIST_PARAM_TYPE))), + CelOverloadDecl.newMemberOverload( + "list_flatten_list_int", + "Flattens a list to the specified level. A negative depth value flattens the list" + + " recursively to its deepest level.", + ListType.create(SimpleType.DYN), + ListType.create(SimpleType.DYN), + SimpleType.INT)), + CelRuntime.CelFunctionBinding.from( + "list_flatten", Collection.class, list -> flatten(list, 1)), CelRuntime.CelFunctionBinding.from( - "list_flatten", Collection.class, list -> flatten(list, 1))), - ; + "list_flatten_list_int", Collection.class, Long.class, CelListsExtensions::flatten)); private final CelFunctionDecl functionDecl; private final ImmutableSet functionBindings; @@ -84,15 +92,15 @@ public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) { } @SuppressWarnings("unchecked") - private static ImmutableList flatten(Collection list, int level) { - Preconditions.checkArgument(level == 1, "recursive flatten is not supported yet."); + private static ImmutableList flatten(Collection list, long depth) { + Preconditions.checkArgument(depth >= 0, "Level must be non-negative"); ImmutableList.Builder builder = ImmutableList.builder(); for (Object element : list) { - if (element instanceof Collection) { - Collection listItem = (Collection) element; - builder.addAll(listItem); - } else { + if (!(element instanceof Collection) || depth == 0) { builder.add(element); + } else { + Collection listItem = (Collection) element; + builder.addAll(flatten(listItem, depth - 1)); } } diff --git a/extensions/src/main/java/dev/cel/extensions/README.md b/extensions/src/main/java/dev/cel/extensions/README.md index e99e6a93f..f240c2a21 100644 --- a/extensions/src/main/java/dev/cel/extensions/README.md +++ b/extensions/src/main/java/dev/cel/extensions/README.md @@ -413,24 +413,38 @@ zero-based. ### Flatten -Flattens a list by one level. Support for flattening to a specified level -will be provided in the future. +Flattens a list by one level, or to the specified level. Providing a negative level will error. Examples: ``` +// Single-level flatten: + [].flatten() // [] [1,[2,3],[4]].flatten() // [1, 2, 3, 4] [1,[2,[3,4]]].flatten() // [1, 2, [3, 4]] [1,2,[],[],[3,4]].flatten() // [1, 2, 3, 4] + +// Recursive flatten +[1,[2,[3,[4]]]].flatten(2) // return [1, 2, 3, [4]] +[1,[2,[3,[4]]]].flatten(3) // return [1, 2, 3, 4] + +// Error +[1,[2,[3,[4]]]].flatten(-1) ``` Note that due to the current limitations of type-checker, a compilation error -will occur if an already flat list is populated. For time being, you must wrap -the list in dyn if you anticipate having to deal with a flat list: +will occur if an already flat list is populated to the argument-less flatten +function. + +For time being, you must explicitly provide 1 as the depth level, or wrap the +list in dyn if you anticipate having to deal with a flat list: ``` [1,2,3].flatten() // error + +// But the following will work: +[1,2,3].flatten(1) // [1,2,3] dyn([1,2,3]).flatten() // [1,2,3] ``` diff --git a/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java index cee8de5b7..da947d879 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java @@ -22,6 +22,7 @@ import dev.cel.bundle.CelFactory; import dev.cel.common.CelValidationException; import dev.cel.parser.CelStandardMacro; +import dev.cel.runtime.CelEvaluationException; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,6 +51,35 @@ public void flattenSingleLevel_success(String expression) throws Exception { assertThat(result).isTrue(); } + @Test + @TestParameters("{expression: '[1,2,3,4].flatten(1) == [1,2,3,4]'}") + @TestParameters("{expression: '[1,[2,[3,[4]]]].flatten(0) == [1,[2,[3,[4]]]]'}") + @TestParameters("{expression: '[1,[2,[3,[4]]]].flatten(2) == [1,2,3,[4]]'}") + @TestParameters("{expression: '[1,[2,[3,4]]].flatten(2) == [1,2,3,4]'}") + @TestParameters("{expression: '[[], [[]], [[[]]]].flatten(2) == [[]]'}") + @TestParameters("{expression: '[[], [[]], [[[]]]].flatten(3) == []'}") + @TestParameters("{expression: '[[], [[]], [[[]]]].flatten(4) == []'}") + // The overload with the depth accepts and returns a List(dyn), so the following is permitted. + @TestParameters("{expression: '[1].flatten(1) == [1]'}") + public void flatten_withDepthValue_success(String expression) throws Exception { + boolean result = (boolean) CEL.createProgram(CEL.compile(expression).getAst()).eval(); + + assertThat(result).isTrue(); + } + + @Test + public void flatten_negativeDepth_throws() { + CelEvaluationException e = + assertThrows( + CelEvaluationException.class, + () -> CEL.createProgram(CEL.compile("[1,2,3,4].flatten(-1)").getAst()).eval()); + + assertThat(e) + .hasMessageThat() + .contains("evaluation error: Function 'list_flatten_list_int' failed"); + assertThat(e).hasCauseThat().hasMessageThat().isEqualTo("Level must be non-negative"); + } + @Test @TestParameters("{expression: '[1].flatten()'}") @TestParameters("{expression: '[{1: 2}].flatten()'}") From 70ae9983389514ac2749eeaebe0c32225d852f02 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 30 Aug 2024 09:28:54 -0700 Subject: [PATCH 31/33] Release 0.7.0 PiperOrigin-RevId: 669351240 --- README.md | 4 ++-- WORKSPACE | 16 ++++++++-------- publish/cel_version.bzl | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b61d940f9..ab11e96e8 100644 --- a/README.md +++ b/README.md @@ -55,14 +55,14 @@ CEL-Java is available in Maven Central Repository. [Download the JARs here][8] o dev.cel cel - 0.6.0 + 0.7.0 ``` **Gradle** ```gradle -implementation 'dev.cel:cel:0.6.0' +implementation 'dev.cel:cel:0.7.0' ``` Then run this example: diff --git a/WORKSPACE b/WORKSPACE index 37c7cd2de..f4cf32ce1 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -64,18 +64,18 @@ load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup") rules_jvm_external_setup() -ANTLR4_VERSION = "4.13.1" +ANTLR4_VERSION = "4.13.2" # Important: there can only be one maven_install rule. Add new maven deps here. maven_install( # keep sorted artifacts = [ - "com.google.auto.value:auto-value:1.10.4", - "com.google.auto.value:auto-value-annotations:1.10.4", + "com.google.auto.value:auto-value:1.11.0", + "com.google.auto.value:auto-value-annotations:1.11.0", "com.google.code.findbugs:annotations:3.0.1", - "com.google.errorprone:error_prone_annotations:2.26.1", - "com.google.guava:guava:33.1.0-jre", - "com.google.guava:guava-testlib:33.1.0-jre", + "com.google.errorprone:error_prone_annotations:2.30.0", + "com.google.guava:guava:33.3.0-jre", + "com.google.guava:guava-testlib:33.3.0-jre", "com.google.protobuf:protobuf-java-util:4.27.3", "com.google.re2j:re2j:1.7", "com.google.testparameterinjector:test-parameter-injector:1.15", @@ -83,7 +83,7 @@ maven_install( "com.google.truth.extensions:truth-proto-extension:1.4.2", "com.google.truth:truth:1.4.2", "org.antlr:antlr4-runtime:" + ANTLR4_VERSION, - "org.jspecify:jspecify:0.3.0", + "org.jspecify:jspecify:1.0.0", "org.threeten:threeten-extra:1.8.0", "org.yaml:snakeyaml:2.2", ], @@ -168,7 +168,7 @@ http_archive( http_jar( name = "antlr4_jar", - sha256 = "bc13a9c57a8dd7d5196888211e5ede657cb64a3ce968608697e4f668251a8487", + sha256 = "eae2dfa119a64327444672aff63e9ec35a20180dc5b8090b7a6ab85125df4d76", urls = ["https://www.antlr.org/download/antlr-" + ANTLR4_VERSION + "-complete.jar"], ) diff --git a/publish/cel_version.bzl b/publish/cel_version.bzl index 96be40f81..bbea9ca1c 100644 --- a/publish/cel_version.bzl +++ b/publish/cel_version.bzl @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. """Maven artifact version for CEL.""" -CEL_VERSION = "0.6.0" +CEL_VERSION = "0.7.0" From bbb46c3b1e3fc3f52fec03183d4fdeee78272801 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 30 Aug 2024 10:46:25 -0700 Subject: [PATCH 32/33] Update protobuf version to 4.28.0 PiperOrigin-RevId: 669376433 --- WORKSPACE | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index f4cf32ce1..4dc16ce61 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -76,7 +76,8 @@ maven_install( "com.google.errorprone:error_prone_annotations:2.30.0", "com.google.guava:guava:33.3.0-jre", "com.google.guava:guava-testlib:33.3.0-jre", - "com.google.protobuf:protobuf-java-util:4.27.3", + "com.google.protobuf:protobuf-java:4.28.0", + "com.google.protobuf:protobuf-java-util:4.28.0", "com.google.re2j:re2j:1.7", "com.google.testparameterinjector:test-parameter-injector:1.15", "com.google.truth.extensions:truth-java8-extension:1.4.2", @@ -95,9 +96,9 @@ maven_install( http_archive( name = "com_google_protobuf", - sha256 = "1535151efbc7893f38b0578e83cac584f2819974f065698976989ec71c1af84a", - strip_prefix = "protobuf-27.3", - urls = ["https://github.com/protocolbuffers/protobuf/archive/v27.3.tar.gz"], + sha256 = "13e7749c30bc24af6ee93e092422f9dc08491c7097efa69461f88eb5f61805ce", + strip_prefix = "protobuf-28.0", + urls = ["https://github.com/protocolbuffers/protobuf/archive/v28.0.tar.gz"], ) # Required by com_google_protobuf From f4292b5c0e4878d34c7ed6b370c47bd9e06d9760 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Fri, 30 Aug 2024 10:58:00 -0700 Subject: [PATCH 33/33] Release 0.7.1 PiperOrigin-RevId: 669380204 --- README.md | 4 ++-- publish/cel_version.bzl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ab11e96e8..7d673e4db 100644 --- a/README.md +++ b/README.md @@ -55,14 +55,14 @@ CEL-Java is available in Maven Central Repository. [Download the JARs here][8] o dev.cel cel - 0.7.0 + 0.7.1 ``` **Gradle** ```gradle -implementation 'dev.cel:cel:0.7.0' +implementation 'dev.cel:cel:0.7.1' ``` Then run this example: diff --git a/publish/cel_version.bzl b/publish/cel_version.bzl index bbea9ca1c..c232b03b8 100644 --- a/publish/cel_version.bzl +++ b/publish/cel_version.bzl @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. """Maven artifact version for CEL.""" -CEL_VERSION = "0.7.0" +CEL_VERSION = "0.7.1"