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/README.md b/README.md
index b61d940f9..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.6.0
+ 0.7.1
```
**Gradle**
```gradle
-implementation 'dev.cel:cel:0.6.0'
+implementation 'dev.cel:cel:0.7.1'
```
Then run this example:
diff --git a/WORKSPACE b/WORKSPACE
index 09fdb0443..4dc16ce61 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"
@@ -52,28 +64,27 @@ 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.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.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.protobuf:protobuf-java:3.25.3",
- "com.google.protobuf:protobuf-java-util:3.25.3",
+ "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: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",
"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",
],
@@ -85,9 +96,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 = "13e7749c30bc24af6ee93e092422f9dc08491c7097efa69461f88eb5f61805ce",
+ strip_prefix = "protobuf-28.0",
+ urls = ["https://github.com/protocolbuffers/protobuf/archive/v28.0.tar.gz"],
)
# Required by com_google_protobuf
@@ -139,10 +150,10 @@ http_archive(
# cel-spec api/expr canonical protos
http_archive(
name = "cel_spec",
- sha256 = "3ee09eb69dbe77722e9dee23dc48dc2cd9f765869fcf5ffb1226587c81791a0b",
- strip_prefix = "cel-spec-0.15.0",
+ sha256 = "7136e18be8881153e05229fc040f8790b634af833d28efb102da00bad640b3ea",
+ strip_prefix = "cel-spec-e363cad95c4da033336f1350de063b16a3e36cd2",
urls = [
- "https://github.com/google/cel-spec/archive/refs/tags/v0.15.0.tar.gz",
+ "https://github.com/google/cel-spec/archive/e363cad95c4da033336f1350de063b16a3e36cd2.tar.gz",
],
)
@@ -158,7 +169,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/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..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",
@@ -36,11 +32,14 @@ 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",
+ "@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",
"@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/bundle/src/test/java/dev/cel/bundle/CelImplTest.java b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java
index ef751df18..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;
@@ -579,6 +580,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 =
@@ -974,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();
@@ -983,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);
@@ -1008,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();
@@ -1770,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/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/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/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/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/main/java/dev/cel/checker/Standard.java b/checker/src/main/java/dev/cel/checker/Standard.java
index f595dde9a..acdc185eb 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(
@@ -419,29 +439,12 @@ 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(
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)));
@@ -456,12 +459,26 @@ 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),
+ CelOverloadDecl.newGlobalOverload(
+ "string_to_bool", "type conversion", SimpleType.BOOL, SimpleType.STRING)));
+
// String functions
celFunctionDeclBuilder.add(
CelFunctionDecl.newFunctionDeclaration(
@@ -693,7 +710,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/java/dev/cel/checker/BUILD.bazel b/checker/src/test/java/dev/cel/checker/BUILD.bazel
index 338dcbb10..ff4b87a34 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",
@@ -26,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",
@@ -48,9 +45,10 @@ 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",
+ "@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",
- "@maven//:com_google_protobuf_protobuf_java",
],
)
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/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);
}
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/standardEnvDump.baseline b/checker/src/test/resources/standardEnvDump.baseline
index 4ef2fa9cf..df1c66553 100644
--- a/checker/src/test/resources/standardEnvDump.baseline
+++ b/checker/src/test/resources/standardEnvDump.baseline
@@ -143,9 +143,12 @@ declare _||_ {
}
declare bool {
value type(bool)
+ function bool_to_bool (bool) -> bool
+ function string_to_bool (string) -> bool
}
declare bytes {
value type(bytes)
+ function bytes_to_bytes (bytes) -> bytes
function string_to_bytes (string) -> bytes
}
declare contains {
@@ -153,11 +156,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,14 +222,13 @@ 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))
- 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
@@ -248,6 +252,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
@@ -257,6 +262,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 {
@@ -265,6 +271,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/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/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/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/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/CelOptions.java b/common/src/main/java/dev/cel/common/CelOptions.java
index fb5ec6ad7..2568099fb 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);
}
/**
@@ -196,6 +211,7 @@ public static Builder current() {
return newBuilder()
.enableReservedIds(true)
.enableUnsignedComparisonAndArithmeticIsUnsigned(true)
+ .enableUnsignedLongs(true)
.enableRegexPartialMatch(true)
.errorOnDuplicateMapKeys(true)
.errorOnIntWrap(true)
@@ -479,6 +495,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/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/CelValidationException.java b/common/src/main/java/dev/cel/common/CelValidationException.java
index 522706e83..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 = 1000;
+ private static final int MAX_ERRORS_TO_REPORT = 100;
private final CelSource source;
private final ImmutableList errors;
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/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/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/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/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/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/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/CelValidationExceptionTest.java b/common/src/test/java/dev/cel/common/CelValidationExceptionTest.java
index be428a64c..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 500 more errors (truncated)");
+ .endsWith("...and 1400 more errors (truncated)");
}
}
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..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,18 +22,18 @@ 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",
"//extensions:optional_library",
"//parser:macro",
"//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",
- "@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/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 af0a673aa..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,18 +25,16 @@ 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",
- "@maven//:com_google_api_grpc_proto_google_common_protos",
+ "@@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_protobuf_protobuf_java",
"@maven//:com_google_testparameterinjector_test_parameter_injector",
"@maven//:junit_junit",
],
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/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/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 5b3ac349c..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",
@@ -27,9 +24,10 @@ java_library(
"//common/values:cel_value_provider",
"//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",
"@maven//:com_google_protobuf_protobuf_java_util",
"@maven//:com_google_testparameterinjector_test_parameter_injector",
"@maven//:junit_junit",
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..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);
@@ -106,9 +104,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 +176,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())
@@ -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/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/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..6b60d77d4
--- /dev/null
+++ b/conformance/src/test/java/dev/cel/conformance/BUILD.bazel
@@ -0,0 +1,154 @@
+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.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",
+ "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/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel
index da8aba9a0..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",
@@ -101,8 +102,9 @@ java_library(
"//common/types",
"//compiler:compiler_builder",
"//runtime",
+ "@@protobuf~//java/core",
"@maven//:com_google_errorprone_error_prone_annotations",
- "@maven//:com_google_protobuf_protobuf_java",
+ "@maven//:com_google_guava_guava",
],
)
@@ -123,8 +125,8 @@ java_library(
"//parser:operator",
"//parser:parser_builder",
"//runtime",
+ "@@protobuf~//java/core",
"@maven//:com_google_guava_guava",
- "@maven//:com_google_protobuf_protobuf_java",
],
)
@@ -136,11 +138,29 @@ 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",
],
)
+
+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/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..eb795341e 100644
--- a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java
+++ b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java
@@ -14,8 +14,13 @@
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 dev.cel.extensions.CelListsExtensions.Function;
import java.util.Set;
/**
@@ -30,7 +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 CelSetsExtensions SET_EXTENSIONS = new CelSetsExtensions();
+ private static final CelListsExtensions LISTS_EXTENSIONS_ALL = new CelListsExtensions();
/**
* Extended functions for string manipulation.
@@ -171,17 +176,25 @@ 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.
*
* 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() {
- return SET_EXTENSIONS;
+ public static CelSetsExtensions sets(CelOptions celOptions) {
+ return new CelSetsExtensions(celOptions);
}
/**
@@ -191,8 +204,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));
}
/**
@@ -202,8 +216,68 @@ 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);
+ }
+
+ /**
+ * 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.
+ *
+ * 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),
+ stream(CelListsExtensions.Function.values())
+ .map(CelListsExtensions.Function::getFunction))
+ .collect(toImmutableSet());
}
private CelExtensions() {}
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..55b5c723e
--- /dev/null
+++ b/extensions/src/main/java/dev/cel/extensions/CelListsExtensions.java
@@ -0,0 +1,109 @@
+// 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.SimpleType;
+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))),
+ 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_list_int", Collection.class, Long.class, CelListsExtensions::flatten));
+
+ 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, long depth) {
+ Preconditions.checkArgument(depth >= 0, "Level must be non-negative");
+ ImmutableList.Builder builder = ImmutableList.builder();
+ for (Object element : list) {
+ if (!(element instanceof Collection) || depth == 0) {
+ builder.add(element);
+ } else {
+ Collection listItem = (Collection) element;
+ builder.addAll(flatten(listItem, depth - 1));
+ }
+ }
+
+ return builder.build();
+ }
+}
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..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,30 +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;
- Function(CelFunctionDecl functionDecl, CelRuntime.CelFunctionBinding... functionBindings) {
+ String getFunction() {
+ return functionDecl.name();
+ }
+
+ 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
@@ -135,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;
+ }
+ }
}
/**
@@ -146,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;
@@ -167,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()) {
@@ -178,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;
}
}
@@ -186,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/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/main/java/dev/cel/extensions/README.md b/extensions/src/main/java/dev/cel/extensions/README.md
index 1163f334c..f240c2a21 100644
--- a/extensions/src/main/java/dev/cel/extensions/README.md
+++ b/extensions/src/main/java/dev/cel/extensions/README.md
@@ -406,3 +406,47 @@ 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, 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 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]
+```
+
+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/BUILD.bazel b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel
index 1edea7cb0..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",
@@ -28,9 +24,11 @@ java_library(
"//parser:macro",
"//runtime",
"//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",
"@maven//:com_google_protobuf_protobuf_java_util",
"@maven//:com_google_testparameterinjector_test_parameter_injector",
"@maven//:junit_junit",
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/CelExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java
index 0b2e7b2cd..26c51b1f4 100644
--- a/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java
+++ b/extensions/src/test/java/dev/cel/extensions/CelExtensionsTest.java
@@ -138,5 +138,28 @@ 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",
+ "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..da947d879
--- /dev/null
+++ b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java
@@ -0,0 +1,92 @@
+// 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 dev.cel.runtime.CelEvaluationException;
+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,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()'}")
+ @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());
+ }
+}
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/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 70396ee45..ef11ff658 100644
--- a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java
+++ b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java
@@ -17,11 +17,15 @@
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;
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,6 +35,7 @@
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 java.util.List;
import org.junit.Test;
@@ -38,15 +43,35 @@
@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("google.api.expr.test.v1.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();
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/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..ff3162cf4 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,17 +88,12 @@
*
*/
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";
- 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 =
@@ -149,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();
@@ -350,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();
@@ -560,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;
}
/**
@@ -637,6 +672,8 @@ public abstract static class SubexpressionOptimizerOptions {
public abstract boolean enableCelBlock();
+ public abstract boolean retainComprehensionStructure();
+
public abstract int subexpressionMaxRecursionDepth();
public abstract ImmutableSet eliminableFunctions();
@@ -693,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();
/**
@@ -727,6 +783,7 @@ public static Builder newBuilder() {
.iterationLimit(500)
.populateMacroCalls(false)
.enableCelBlock(false)
+ .retainComprehensionStructure(true)
.subexpressionMaxRecursionDepth(0);
}
@@ -738,7 +795,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/AstMutatorTest.java b/optimizer/src/test/java/dev/cel/optimizer/AstMutatorTest.java
index cdfa1cb00..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();
@@ -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/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 9813ee266..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,12 +17,16 @@
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;
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,7 +39,7 @@
import dev.cel.parser.CelStandardMacro;
import dev.cel.parser.CelUnparser;
import dev.cel.parser.CelUnparserFactory;
-import dev.cel.testing.testdata.proto3.TestAllTypesProto.TestAllTypes;
+import dev.cel.runtime.CelRuntime.CelFunctionBinding;
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)
+ .setContainer("google.api.expr.test.v1.proto3")
+ .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 {
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..1f7de0a7e 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;
@@ -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")
@@ -258,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());
@@ -272,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());
@@ -286,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());
@@ -319,7 +323,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())
@@ -352,6 +356,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(
@@ -461,6 +467,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/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerTest.java
index f4cec706d..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;
@@ -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 b18460018..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,24 @@ 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
+[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: 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_COMMON_SUBEXPR_COMPREHENSION_STRUCTURE_RETAINED]: true
[BLOCK_RECURSION_DEPTH_1]: true
[BLOCK_RECURSION_DEPTH_2]: true
[BLOCK_RECURSION_DEPTH_3]: true
@@ -356,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
@@ -372,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
@@ -388,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
@@ -402,17 +444,18 @@ 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_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)
+[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])
@@ -420,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]])
@@ -436,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
@@ -452,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
@@ -468,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)
@@ -484,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)
@@ -500,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)
@@ -516,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)
@@ -532,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])
@@ -548,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
@@ -564,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
@@ -580,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
@@ -596,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
@@ -612,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
@@ -628,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
@@ -644,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
@@ -660,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))
@@ -676,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/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_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_ast_block_common_subexpr_only.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline
index c1ad64871..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,59 +1240,75 @@ 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
- 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
+CALL [1] {
+ 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
}
}
}
@@ -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
}
}
}
@@ -2151,6 +1876,119 @@ 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 }
+ }
+ }
+ 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]
=====>
@@ -2317,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: {
@@ -2338,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: {
@@ -2364,7 +2202,7 @@ CALL [1] {
function: _+_
args: {
IDENT [25] {
- name: @x:0
+ name: @ac:1:0
}
LIST [26] {
elements: {
@@ -2378,7 +2216,7 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2389,7 +2227,7 @@ CALL [1] {
}
result: {
IDENT [29] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2439,7 +2277,7 @@ CALL [1] {
function: _||_
args: {
COMPREHENSION [10] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [11] {
elements: {
@@ -2458,7 +2296,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [16] { value: false }
}
@@ -2470,7 +2308,7 @@ CALL [1] {
function: !_
args: {
IDENT [19] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2482,7 +2320,7 @@ CALL [1] {
function: _||_
args: {
IDENT [21] {
- name: @x:0
+ name: @ac:0:0
}
CALL [22] {
function: _>_
@@ -2491,7 +2329,7 @@ CALL [1] {
function: _-_
args: {
IDENT [24] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [25] { value: 1 }
}
@@ -2504,7 +2342,7 @@ CALL [1] {
}
result: {
IDENT [27] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2527,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
}
}
}
@@ -2538,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: {
@@ -2560,7 +2398,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [14] {
elements: {
@@ -2575,7 +2413,7 @@ CALL [1] {
function: _+_
args: {
IDENT [17] {
- name: @x:0
+ name: @ac:1:0
}
LIST [18] {
elements: {
@@ -2596,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: {
@@ -2616,7 +2454,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2637,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 1b081c43c..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
}
}
}
@@ -2592,6 +2472,187 @@ 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: @it:1:0
+ }
+ CONSTANT [9] { value: 1 }
+ }
+ }
+ LIST [10] {
+ elements: {
+ IDENT [11] {
+ name: @index1
+ }
+ }
+ }
+ CALL [12] {
+ function: _+_
+ args: {
+ IDENT [13] {
+ name: @ac:1:0
+ }
+ IDENT [14] {
+ name: @index2
+ }
+ }
+ }
+ }
+ }
+ CALL [15] {
+ function: _==_
+ args: {
+ COMPREHENSION [16] {
+ iter_var: @it:0:0
+ iter_range: {
+ IDENT [17] {
+ name: @index0
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [18] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [19] { value: true }
+ }
+ loop_step: {
+ CALL [20] {
+ function: _+_
+ args: {
+ IDENT [21] {
+ name: @ac:0:0
+ }
+ LIST [22] {
+ elements: {
+ COMPREHENSION [23] {
+ iter_var: @it:1:0
+ iter_range: {
+ IDENT [24] {
+ name: @index0
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [25] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [26] { value: true }
+ }
+ loop_step: {
+ IDENT [27] {
+ name: @index3
+ }
+ }
+ result: {
+ IDENT [28] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [29] {
+ name: @ac:0:0
+ }
+ }
+ }
+ COMPREHENSION [30] {
+ iter_var: @it:0:0
+ iter_range: {
+ IDENT [31] {
+ name: @index0
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [32] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [33] { value: true }
+ }
+ loop_step: {
+ CALL [34] {
+ function: _+_
+ args: {
+ IDENT [35] {
+ name: @ac:0:0
+ }
+ LIST [36] {
+ elements: {
+ COMPREHENSION [37] {
+ iter_var: @it:1:0
+ iter_range: {
+ IDENT [38] {
+ name: @index0
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [39] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [40] { value: true }
+ }
+ loop_step: {
+ IDENT [41] {
+ name: @index3
+ }
+ }
+ result: {
+ IDENT [42] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [43] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ }
+}
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]
=====>
@@ -2781,7 +2842,7 @@ CALL [1] {
function: _+_
args: {
IDENT [15] {
- name: @x:0
+ name: @ac:1:0
}
IDENT [16] {
name: @index3
@@ -2804,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: {
@@ -2825,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: {
@@ -2853,7 +2914,7 @@ CALL [1] {
}
result: {
IDENT [33] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2864,7 +2925,7 @@ CALL [1] {
}
result: {
IDENT [34] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2924,7 +2985,7 @@ CALL [1] {
function: _-_
args: {
IDENT [16] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [17] { value: 1 }
}
@@ -2942,7 +3003,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
IDENT [23] {
name: @index5
@@ -2955,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 }
}
@@ -2973,7 +3034,7 @@ CALL [1] {
function: !_
args: {
IDENT [30] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2987,7 +3048,7 @@ CALL [1] {
}
result: {
IDENT [32] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -3010,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
}
}
}
@@ -3021,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
}
}
}
@@ -3055,7 +3116,7 @@ CALL [1] {
function: _+_
args: {
IDENT [18] {
- name: @x:0
+ name: @ac:1:0
}
IDENT [19] {
name: @index4
@@ -3083,7 +3144,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
IDENT [27] {
name: @index7
@@ -3093,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: {
@@ -3119,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: {
@@ -3141,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 1d3045ff6..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
}
}
}
@@ -2368,6 +2266,129 @@ 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: {
+ CALL [4] {
+ function: _+_
+ args: {
+ IDENT [5] {
+ name: @it:1:0
+ }
+ CONSTANT [6] { value: 1 }
+ }
+ }
+ }
+ }
+ COMPREHENSION [7] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [8] {
+ elements: {
+ CONSTANT [9] { value: 1 }
+ CONSTANT [10] { value: 2 }
+ CONSTANT [11] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [12] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [13] { value: true }
+ }
+ loop_step: {
+ CALL [14] {
+ function: _+_
+ args: {
+ IDENT [15] {
+ name: @ac:1:0
+ }
+ IDENT [16] {
+ name: @index0
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [17] {
+ name: @ac:1:0
+ }
+ }
+ }
+ CALL [18] {
+ function: _+_
+ args: {
+ IDENT [19] {
+ name: @ac:0:0
+ }
+ LIST [20] {
+ elements: {
+ IDENT [21] {
+ name: @index1
+ }
+ }
+ }
+ }
+ }
+ COMPREHENSION [22] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [23] {
+ elements: {
+ CONSTANT [24] { value: 1 }
+ CONSTANT [25] { value: 2 }
+ CONSTANT [26] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [27] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [28] { value: true }
+ }
+ loop_step: {
+ IDENT [29] {
+ name: @index2
+ }
+ }
+ result: {
+ IDENT [30] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [31] {
+ function: _==_
+ args: {
+ IDENT [32] {
+ name: @index3
+ }
+ IDENT [33] {
+ name: @index3
+ }
+ }
+ }
+ }
+}
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]
=====>
@@ -2549,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: {
@@ -2570,7 +2591,7 @@ CALL [1] {
function: _+_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:1:0
}
IDENT [23] {
name: @index2
@@ -2580,7 +2601,7 @@ CALL [1] {
}
result: {
IDENT [24] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2588,7 +2609,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2600,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: {
@@ -2623,7 +2644,7 @@ CALL [1] {
}
result: {
IDENT [34] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2697,7 +2718,7 @@ CALL [1] {
function: _-_
args: {
IDENT [16] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [17] { value: 1 }
}
@@ -2716,7 +2737,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
IDENT [23] {
name: @index2
@@ -2729,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 }
}
@@ -2747,7 +2768,7 @@ CALL [1] {
function: !_
args: {
IDENT [30] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2761,7 +2782,7 @@ CALL [1] {
}
result: {
IDENT [32] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2784,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
}
}
}
@@ -2795,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
}
}
}
@@ -2817,7 +2838,7 @@ CALL [1] {
}
}
COMPREHENSION [13] {
- iter_var: @c:0
+ iter_var: @it:1:0
iter_range: {
LIST [14] {
elements: {
@@ -2826,7 +2847,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [17] {
elements: {
@@ -2841,7 +2862,7 @@ CALL [1] {
function: _+_
args: {
IDENT [20] {
- name: @x:0
+ name: @ac:1:0
}
IDENT [21] {
name: @index2
@@ -2851,7 +2872,7 @@ CALL [1] {
}
result: {
IDENT [22] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2872,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: {
@@ -2893,7 +2914,7 @@ CALL [1] {
function: _+_
args: {
IDENT [32] {
- name: @x:1
+ name: @ac:0:0
}
IDENT [33] {
name: @index4
@@ -2903,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 f9c1f2a42..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,87 +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
- }
- }
- accu_var: @x:0
- accu_init: {
- CONSTANT [9] { value: false }
- }
- loop_condition: {
- CALL [10] {
- function: @not_strictly_false
- args: {
- CALL [11] {
- function: !_
- args: {
- IDENT [12] {
- name: @x:0
- }
- }
- }
- }
- }
- }
- loop_step: {
- CALL [13] {
- function: _||_
- args: {
- IDENT [14] {
- name: @x:0
- }
- CALL [15] {
- function: _>_
- args: {
- IDENT [16] {
- name: @c:0
- }
- CONSTANT [17] { value: 0 }
- }
- }
+ LIST [4] {
+ elements: {
+ CONSTANT [5] { value: 1 }
}
}
}
- result: {
- IDENT [18] {
- name: @x:0
- }
- }
- }
- COMPREHENSION [19] {
- iter_var: @c:1
- iter_range: {
- IDENT [20] {
- name: @index0
- }
- }
- accu_var: @x:1
+ accu_var: @ac:0:0
accu_init: {
- CONSTANT [21] { value: false }
+ CONSTANT [6] { value: false }
}
loop_condition: {
- CALL [22] {
+ CALL [7] {
function: @not_strictly_false
args: {
- CALL [23] {
+ CALL [8] {
function: !_
args: {
- IDENT [24] {
- name: @x:1
+ IDENT [9] {
+ name: @ac:0:0
}
}
}
@@ -1287,150 +1228,52 @@ CALL [1] {
}
}
loop_step: {
- CALL [25] {
+ CALL [10] {
function: _||_
args: {
- IDENT [26] {
- name: @x:1
+ IDENT [11] {
+ name: @ac:0:0
}
- CALL [27] {
+ CALL [12] {
function: _>_
args: {
- IDENT [28] {
- name: @c:1
+ IDENT [13] {
+ name: @it:0:0
}
- CONSTANT [29] { value: 0 }
+ CONSTANT [14] { value: 0 }
}
}
}
}
}
result: {
- IDENT [30] {
- name: @x:1
- }
- }
- }
- CALL [31] {
- function: _+_
- 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
- }
- }
- }
- }
+ IDENT [15] {
+ name: @ac:0:0
}
}
}
- COMPREHENSION [38] {
- iter_var: @c:2
+ COMPREHENSION [16] {
+ iter_var: @it:0:0
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 }
- }
- }
- }
- }
- }
- result: {
- IDENT [49] {
- name: @x:2
- }
- }
- }
- CALL [50] {
- function: _+_
- args: {
- IDENT [51] {
- name: @index4
- }
- CALL [52] {
- function: size
- args: {
- LIST [53] {
- elements: {
- IDENT [54] {
- name: @index5
- }
- }
- }
+ LIST [17] {
+ elements: {
+ CONSTANT [18] { value: 2 }
}
}
}
- }
- COMPREHENSION [55] {
- iter_var: @c:3
- iter_range: {
- IDENT [56] {
- name: @index1
- }
- }
- accu_var: @x:3
+ accu_var: @ac:0:0
accu_init: {
- CONSTANT [57] { value: false }
+ CONSTANT [19] { value: false }
}
loop_condition: {
- CALL [58] {
+ CALL [20] {
function: @not_strictly_false
args: {
- CALL [59] {
+ CALL [21] {
function: !_
args: {
- IDENT [60] {
- name: @x:3
+ IDENT [22] {
+ name: @ac:0:0
}
}
}
@@ -1438,381 +1281,124 @@ CALL [1] {
}
}
loop_step: {
- CALL [61] {
+ CALL [23] {
function: _||_
args: {
- IDENT [62] {
- name: @x:3
+ IDENT [24] {
+ name: @ac:0:0
}
- CALL [63] {
+ CALL [25] {
function: _>_
args: {
- IDENT [64] {
- name: @c:3
+ IDENT [26] {
+ name: @it:0:0
}
- CONSTANT [65] { value: 1 }
+ CONSTANT [27] { value: 1 }
}
}
}
}
}
result: {
- IDENT [66] {
- name: @x:3
+ IDENT [28] {
+ name: @ac:0:0
}
}
}
- CALL [67] {
- function: _+_
+ CALL [29] {
+ function: size
args: {
- IDENT [68] {
- name: @index6
- }
- CALL [69] {
- function: size
- args: {
- LIST [70] {
- elements: {
- IDENT [71] {
- name: @index7
- }
- }
- }
- }
- }
- }
- }
- }
- }
- CALL [72] {
- function: _==_
- args: {
- IDENT [73] {
- name: @index8
- }
- CONSTANT [74] { 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" }
- }
- }
- COMPREHENSION [7] {
- iter_var: @c:0
- iter_range: {
- IDENT [8] {
- name: @index0
- }
- }
- accu_var: @x:0
- accu_init: {
- CONSTANT [9] { value: false }
- }
- loop_condition: {
- CALL [10] {
- function: @not_strictly_false
- args: {
- CALL [11] {
- function: !_
- args: {
- IDENT [12] {
- name: @x:0
- }
- }
- }
- }
- }
- }
- loop_step: {
- CALL [13] {
- function: _||_
- args: {
- IDENT [14] {
- name: @x:0
- }
- CALL [15] {
- function: _>_
- args: {
- IDENT [16] {
- name: @c:0
- }
- CONSTANT [17] { value: 0 }
- }
- }
- }
- }
- }
- result: {
- IDENT [18] {
- name: @x:0
- }
- }
- }
- COMPREHENSION [19] {
- iter_var: @c:1
- iter_range: {
- IDENT [20] {
- name: @index0
- }
- }
- accu_var: @x:1
- accu_init: {
- CONSTANT [21] { value: false }
- }
- loop_condition: {
- CALL [22] {
- function: @not_strictly_false
- args: {
- CALL [23] {
- function: !_
- args: {
- IDENT [24] {
- name: @x:1
- }
- }
- }
- }
- }
- }
- loop_step: {
- CALL [25] {
- function: _||_
- args: {
- IDENT [26] {
- name: @x:1
- }
- CALL [27] {
- function: _>_
- args: {
- IDENT [28] {
- name: @c:1
- }
- CONSTANT [29] { value: 0 }
- }
+ LIST [30] {
+ elements: {
+ IDENT [31] {
+ name: @index0
}
}
}
}
- result: {
- IDENT [30] {
- name: @x:1
- }
- }
}
- COMPREHENSION [31] {
- iter_var: @c:2
- iter_range: {
- 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" }
- }
+ CALL [32] {
+ function: size
+ args: {
+ LIST [33] {
+ elements: {
+ IDENT [34] {
+ name: @index1
}
}
}
}
- result: {
- IDENT [42] {
- name: @x:2
- }
- }
}
- CALL [43] {
+ CALL [35] {
function: _+_
args: {
- CALL [44] {
+ CALL [36] {
function: _+_
args: {
- LIST [45] {
- elements: {
- IDENT [46] {
+ CALL [37] {
+ function: _+_
+ args: {
+ IDENT [38] {
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
+ IDENT [39] {
+ name: @index2
}
}
}
- }
- }
- }
- loop_step: {
- CALL [57] {
- function: _||_
- args: {
- IDENT [58] {
- name: @x:3
- }
- CALL [59] {
- function: _==_
- args: {
- IDENT [60] {
- name: @c:3
- }
- CONSTANT [61] { value: "a" }
- }
+ IDENT [40] {
+ name: @index3
}
}
}
- }
- result: {
- IDENT [62] {
- name: @x:3
+ IDENT [41] {
+ name: @index3
}
}
}
}
}
- CALL [63] {
+ CALL [42] {
function: _==_
args: {
- CALL [64] {
- function: _+_
- args: {
- IDENT [65] {
- name: @index5
- }
- LIST [66] {
- elements: {
- IDENT [67] {
- name: @index6
- }
- }
- }
- }
- }
- LIST [68] {
- elements: {
- CONSTANT [69] { value: true }
- CONSTANT [70] { value: true }
- CONSTANT [71] { value: true }
- CONSTANT [72] { value: true }
- }
+ IDENT [43] {
+ name: @index4
}
+ CONSTANT [44] { 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 }
- }
- }
- COMPREHENSION [5] {
- iter_var: @c:0
+ elements: {
+ 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,38 +1406,40 @@ 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
+ COMPREHENSION [16] {
+ iter_var: @it:0:1
iter_range: {
- IDENT [18] {
- name: @index0
+ LIST [17] {
+ elements: {
+ CONSTANT [18] { value: "a" }
+ }
}
}
- accu_var: @x:1
+ accu_var: @ac:0:1
accu_init: {
CONSTANT [19] { value: false }
}
@@ -1863,7 +1451,7 @@ CALL [1] {
function: !_
args: {
IDENT [22] {
- name: @x:1
+ name: @ac:0:1
}
}
}
@@ -1875,15 +1463,15 @@ CALL [1] {
function: _||_
args: {
IDENT [24] {
- name: @x:1
+ name: @ac:0:1
}
CALL [25] {
- function: _>_
+ function: _==_
args: {
IDENT [26] {
- name: @c:1
+ name: @it:0:1
}
- CONSTANT [27] { value: 0 }
+ CONSTANT [27] { value: "a" }
}
}
}
@@ -1891,30 +1479,101 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:1
+ name: @ac:0:1
}
}
}
- COMPREHENSION [29] {
- iter_var: @c:2
- iter_range: {
+ LIST [29] {
+ elements: {
IDENT [30] {
name: @index0
}
}
- accu_var: @x:2
+ }
+ LIST [31] {
+ elements: {
+ IDENT [32] {
+ name: @index1
+ }
+ }
+ }
+ CALL [33] {
+ function: _+_
+ args: {
+ CALL [34] {
+ function: _+_
+ args: {
+ CALL [35] {
+ function: _+_
+ args: {
+ IDENT [36] {
+ name: @index2
+ }
+ IDENT [37] {
+ name: @index2
+ }
+ }
+ }
+ IDENT [38] {
+ name: @index3
+ }
+ }
+ }
+ IDENT [39] {
+ name: @index3
+ }
+ }
+ }
+ }
+ }
+ CALL [40] {
+ function: _==_
+ args: {
+ IDENT [41] {
+ name: @index4
+ }
+ LIST [42] {
+ elements: {
+ CONSTANT [43] { value: true }
+ CONSTANT [44] { value: true }
+ CONSTANT [45] { value: true }
+ CONSTANT [46] { 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 [31] { value: false }
+ CONSTANT [6] { value: false }
}
loop_condition: {
- CALL [32] {
+ CALL [7] {
function: @not_strictly_false
args: {
- CALL [33] {
+ CALL [8] {
function: !_
args: {
- IDENT [34] {
- name: @x:2
+ IDENT [9] {
+ name: @ac:0:0
}
}
}
@@ -1922,52 +1581,69 @@ CALL [1] {
}
}
loop_step: {
- CALL [35] {
+ CALL [10] {
function: _||_
args: {
- IDENT [36] {
- name: @x:2
+ IDENT [11] {
+ name: @ac:0:0
}
- CALL [37] {
+ CALL [12] {
function: _>_
args: {
- IDENT [38] {
- name: @c:2
+ IDENT [13] {
+ name: @it:0:0
}
- CONSTANT [39] { value: 1 }
+ CONSTANT [14] { value: 0 }
}
}
}
}
}
result: {
- IDENT [40] {
- name: @x:2
+ 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 }
+ }
}
}
}
- COMPREHENSION [41] {
- iter_var: @c:3
+ COMPREHENSION [21] {
+ iter_var: @it:0:0
iter_range: {
- LIST [42] {
+ LIST [22] {
elements: {
- CONSTANT [43] { value: 2 }
+ CONSTANT [23] { value: 1 }
}
}
}
- accu_var: @x:3
+ accu_var: @ac:0:0
accu_init: {
- CONSTANT [44] { value: false }
+ CONSTANT [24] { value: false }
}
loop_condition: {
- CALL [45] {
+ CALL [25] {
function: @not_strictly_false
args: {
- CALL [46] {
+ CALL [26] {
function: !_
args: {
- IDENT [47] {
- name: @x:3
+ IDENT [27] {
+ name: @ac:0:0
}
}
}
@@ -1975,54 +1651,79 @@ CALL [1] {
}
}
loop_step: {
- CALL [48] {
- function: _||_
+ IDENT [28] {
+ name: @index1
+ }
+ }
+ result: {
+ IDENT [29] {
+ name: @ac:0:0
+ }
+ }
+ }
+ COMPREHENSION [30] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [31] {
+ elements: {
+ CONSTANT [32] { value: 2 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ CONSTANT [33] { value: false }
+ }
+ loop_condition: {
+ CALL [34] {
+ function: @not_strictly_false
args: {
- IDENT [49] {
- name: @x:3
- }
- CALL [50] {
- function: _>_
+ CALL [35] {
+ function: !_
args: {
- IDENT [51] {
- name: @c:3
+ IDENT [36] {
+ name: @ac:0:0
}
- CONSTANT [52] { value: 1 }
}
}
}
}
}
+ loop_step: {
+ 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
}
}
}
@@ -2303,6 +2004,126 @@ 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: {
+ CALL [3] {
+ function: _+_
+ args: {
+ IDENT [4] {
+ name: @ac:1:0
+ }
+ LIST [5] {
+ elements: {
+ CALL [6] {
+ function: _+_
+ args: {
+ IDENT [7] {
+ name: @it:1:0
+ }
+ CONSTANT [8] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ LIST [9] {
+ elements: {
+ COMPREHENSION [10] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [11] {
+ elements: {
+ CONSTANT [12] { value: 1 }
+ CONSTANT [13] { value: 2 }
+ CONSTANT [14] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [15] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [16] { value: true }
+ }
+ loop_step: {
+ IDENT [17] {
+ name: @index0
+ }
+ }
+ result: {
+ IDENT [18] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ COMPREHENSION [19] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [20] {
+ elements: {
+ CONSTANT [21] { value: 1 }
+ CONSTANT [22] { value: 2 }
+ CONSTANT [23] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [24] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [25] { value: true }
+ }
+ loop_step: {
+ CALL [26] {
+ function: _+_
+ args: {
+ IDENT [27] {
+ name: @ac:0:0
+ }
+ IDENT [28] {
+ name: @index1
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [29] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [30] {
+ function: _==_
+ args: {
+ IDENT [31] {
+ name: @index2
+ }
+ IDENT [32] {
+ 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]
=====>
@@ -2474,7 +2295,7 @@ CALL [1] {
function: _+_
args: {
IDENT [14] {
- name: @x:0
+ name: @ac:1:0
}
LIST [15] {
elements: {
@@ -2491,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: {
@@ -2514,7 +2335,7 @@ CALL [1] {
}
result: {
IDENT [25] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2526,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: {
@@ -2547,7 +2368,7 @@ CALL [1] {
function: _+_
args: {
IDENT [32] {
- name: @x:1
+ name: @ac:0:0
}
IDENT [33] {
name: @index3
@@ -2557,7 +2378,7 @@ CALL [1] {
}
result: {
IDENT [34] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2624,7 +2445,7 @@ CALL [1] {
function: _||_
args: {
IDENT [16] {
- name: @x:0
+ name: @ac:0:0
}
CALL [17] {
function: _>_
@@ -2633,7 +2454,7 @@ CALL [1] {
function: _-_
args: {
IDENT [19] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [20] { value: 1 }
}
@@ -2644,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 }
}
@@ -2662,7 +2483,7 @@ CALL [1] {
function: !_
args: {
IDENT [27] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2676,7 +2497,7 @@ CALL [1] {
}
result: {
IDENT [29] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2707,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
}
}
}
@@ -2718,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
}
}
}
@@ -2729,7 +2550,7 @@ CALL [1] {
function: _+_
args: {
IDENT [10] {
- name: @x:0
+ name: @ac:1:0
}
LIST [11] {
elements: {
@@ -2751,7 +2572,7 @@ CALL [1] {
function: _+_
args: {
IDENT [16] {
- name: @x:1
+ name: @ac:0:0
}
LIST [17] {
elements: {
@@ -2772,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: {
@@ -2784,7 +2605,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [26] {
elements: {
@@ -2801,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: {
@@ -2823,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 a640f81da..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
}
}
}
@@ -2252,6 +1953,123 @@ 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: {
+ COMPREHENSION [3] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [4] {
+ elements: {
+ CONSTANT [5] { value: 1 }
+ CONSTANT [6] { value: 2 }
+ CONSTANT [7] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [8] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [9] { value: true }
+ }
+ loop_step: {
+ CALL [10] {
+ function: _+_
+ args: {
+ IDENT [11] {
+ name: @ac:1:0
+ }
+ LIST [12] {
+ elements: {
+ CALL [13] {
+ function: _+_
+ args: {
+ IDENT [14] {
+ name: @it:1:0
+ }
+ CONSTANT [15] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [16] {
+ name: @ac:1:0
+ }
+ }
+ }
+ COMPREHENSION [17] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [18] {
+ elements: {
+ CONSTANT [19] { value: 1 }
+ CONSTANT [20] { value: 2 }
+ CONSTANT [21] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [22] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [23] { value: true }
+ }
+ loop_step: {
+ CALL [24] {
+ function: _+_
+ args: {
+ IDENT [25] {
+ name: @ac:0:0
+ }
+ LIST [26] {
+ elements: {
+ IDENT [27] {
+ name: @index0
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [28] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [29] {
+ function: _==_
+ args: {
+ IDENT [30] {
+ name: @index1
+ }
+ IDENT [31] {
+ 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]
=====>
@@ -2417,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: {
@@ -2438,7 +2256,7 @@ CALL [1] {
function: _+_
args: {
IDENT [18] {
- name: @x:0
+ name: @ac:1:0
}
LIST [19] {
elements: {
@@ -2455,7 +2273,7 @@ CALL [1] {
}
result: {
IDENT [23] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2465,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: {
@@ -2486,7 +2304,7 @@ CALL [1] {
function: _+_
args: {
IDENT [30] {
- name: @x:1
+ name: @ac:0:0
}
LIST [31] {
elements: {
@@ -2500,7 +2318,7 @@ CALL [1] {
}
result: {
IDENT [33] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2542,7 +2360,7 @@ CALL [1] {
}
}
COMPREHENSION [8] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [9] {
elements: {
@@ -2567,7 +2385,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [16] { value: false }
}
@@ -2579,7 +2397,7 @@ CALL [1] {
function: !_
args: {
IDENT [19] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2591,7 +2409,7 @@ CALL [1] {
function: _||_
args: {
IDENT [21] {
- name: @x:0
+ name: @ac:0:0
}
CALL [22] {
function: _>_
@@ -2600,7 +2418,7 @@ CALL [1] {
function: _-_
args: {
IDENT [24] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [25] { value: 1 }
}
@@ -2613,7 +2431,7 @@ CALL [1] {
}
result: {
IDENT [27] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2644,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
}
}
}
@@ -2655,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: {
@@ -2672,7 +2490,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [13] {
elements: {
@@ -2687,7 +2505,7 @@ CALL [1] {
function: _+_
args: {
IDENT [16] {
- name: @x:0
+ name: @ac:1:0
}
LIST [17] {
elements: {
@@ -2708,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: {
@@ -2736,7 +2554,7 @@ CALL [1] {
function: _+_
args: {
IDENT [27] {
- name: @x:1
+ name: @ac:0:0
}
LIST [28] {
elements: {
@@ -2757,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 ba9b61292..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
}
}
}
@@ -2222,6 +1926,123 @@ 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: {
+ COMPREHENSION [4] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [5] {
+ elements: {
+ CONSTANT [6] { value: 1 }
+ CONSTANT [7] { value: 2 }
+ CONSTANT [8] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [9] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [10] { value: true }
+ }
+ loop_step: {
+ CALL [11] {
+ function: _+_
+ args: {
+ IDENT [12] {
+ name: @ac:1:0
+ }
+ LIST [13] {
+ elements: {
+ CALL [14] {
+ function: _+_
+ args: {
+ IDENT [15] {
+ name: @it:1:0
+ }
+ CONSTANT [16] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [17] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ COMPREHENSION [18] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [19] {
+ elements: {
+ CONSTANT [20] { value: 1 }
+ CONSTANT [21] { value: 2 }
+ CONSTANT [22] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [23] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [24] { value: true }
+ }
+ loop_step: {
+ CALL [25] {
+ function: _+_
+ args: {
+ IDENT [26] {
+ name: @ac:0:0
+ }
+ IDENT [27] {
+ name: @index0
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [28] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [29] {
+ function: _==_
+ args: {
+ IDENT [30] {
+ name: @index1
+ }
+ IDENT [31] {
+ 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]
=====>
@@ -2389,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: {
@@ -2410,7 +2231,7 @@ CALL [1] {
function: _+_
args: {
IDENT [19] {
- name: @x:0
+ name: @ac:1:0
}
LIST [20] {
elements: {
@@ -2427,7 +2248,7 @@ CALL [1] {
}
result: {
IDENT [24] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2439,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: {
@@ -2460,7 +2281,7 @@ CALL [1] {
function: _+_
args: {
IDENT [31] {
- name: @x:1
+ name: @ac:0:0
}
IDENT [32] {
name: @index2
@@ -2470,7 +2291,7 @@ CALL [1] {
}
result: {
IDENT [33] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2517,7 +2338,7 @@ CALL [1] {
function: _||_
args: {
COMPREHENSION [9] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [10] {
elements: {
@@ -2542,7 +2363,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [17] { value: false }
}
@@ -2554,7 +2375,7 @@ CALL [1] {
function: !_
args: {
IDENT [20] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2566,7 +2387,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
CALL [23] {
function: _>_
@@ -2575,7 +2396,7 @@ CALL [1] {
function: _-_
args: {
IDENT [25] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [26] { value: 1 }
}
@@ -2588,7 +2409,7 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2611,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
}
}
}
@@ -2622,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: {
@@ -2644,7 +2465,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [14] {
elements: {
@@ -2659,7 +2480,7 @@ CALL [1] {
function: _+_
args: {
IDENT [17] {
- name: @x:0
+ name: @ac:1:0
}
LIST [18] {
elements: {
@@ -2680,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: {
@@ -2700,7 +2521,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2721,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 b68e6eaf1..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
@@ -1711,38 +1315,29 @@ CALL [1] {
LIST [2] {
elements: {
LIST [3] {
- elements: {
- CONSTANT [4] { value: 1 }
- }
- }
- }
- }
- CALL [5] {
- function: _&&_
- args: {
- CALL [6] {
- function: _&&_
- args: {
- COMPREHENSION [7] {
- iter_var: @c:0
+ 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
}
}
}
@@ -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
}
}
}
@@ -2207,6 +1920,123 @@ 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: {
+ CALL [3] {
+ function: _+_
+ args: {
+ IDENT [4] {
+ name: @ac:0:0
+ }
+ LIST [5] {
+ elements: {
+ COMPREHENSION [6] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [7] {
+ elements: {
+ CONSTANT [8] { value: 1 }
+ CONSTANT [9] { value: 2 }
+ CONSTANT [10] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [11] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [12] { value: true }
+ }
+ loop_step: {
+ CALL [13] {
+ function: _+_
+ args: {
+ IDENT [14] {
+ name: @ac:1:0
+ }
+ LIST [15] {
+ elements: {
+ CALL [16] {
+ function: _+_
+ args: {
+ IDENT [17] {
+ name: @it:1:0
+ }
+ CONSTANT [18] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [19] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ COMPREHENSION [20] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [21] {
+ elements: {
+ CONSTANT [22] { value: 1 }
+ CONSTANT [23] { value: 2 }
+ CONSTANT [24] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [25] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [26] { value: true }
+ }
+ loop_step: {
+ IDENT [27] {
+ name: @index0
+ }
+ }
+ result: {
+ IDENT [28] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [29] {
+ function: _==_
+ args: {
+ IDENT [30] {
+ name: @index1
+ }
+ IDENT [31] {
+ 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]
=====>
@@ -2375,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: {
@@ -2401,7 +2231,7 @@ CALL [1] {
function: _+_
args: {
IDENT [21] {
- name: @x:0
+ name: @ac:1:0
}
LIST [22] {
elements: {
@@ -2418,7 +2248,7 @@ CALL [1] {
}
result: {
IDENT [26] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2432,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: {
@@ -2455,7 +2285,7 @@ CALL [1] {
}
result: {
IDENT [33] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2502,7 +2332,7 @@ CALL [1] {
function: _||_
args: {
COMPREHENSION [9] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [10] {
elements: {
@@ -2527,7 +2357,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [17] { value: false }
}
@@ -2539,7 +2369,7 @@ CALL [1] {
function: !_
args: {
IDENT [20] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2551,7 +2381,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
CALL [23] {
function: _>_
@@ -2560,7 +2390,7 @@ CALL [1] {
function: _-_
args: {
IDENT [25] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [26] { value: 1 }
}
@@ -2573,7 +2403,7 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2596,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
}
}
}
@@ -2607,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: {
@@ -2629,7 +2459,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [14] {
elements: {
@@ -2644,7 +2474,7 @@ CALL [1] {
function: _+_
args: {
IDENT [17] {
- name: @x:0
+ name: @ac:1:0
}
LIST [18] {
elements: {
@@ -2665,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: {
@@ -2685,7 +2515,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2706,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 410c1ff1a..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)
-=====>
-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
+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: {
+ 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
}
}
}
@@ -2198,6 +1917,120 @@ 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: {
+ COMPREHENSION [3] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [4] {
+ elements: {
+ CONSTANT [5] { value: 1 }
+ CONSTANT [6] { value: 2 }
+ CONSTANT [7] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [8] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [9] { value: true }
+ }
+ loop_step: {
+ CALL [10] {
+ function: _+_
+ args: {
+ IDENT [11] {
+ name: @ac:0:0
+ }
+ LIST [12] {
+ elements: {
+ COMPREHENSION [13] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [14] {
+ elements: {
+ CONSTANT [15] { value: 1 }
+ CONSTANT [16] { value: 2 }
+ CONSTANT [17] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [18] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [19] { value: true }
+ }
+ loop_step: {
+ CALL [20] {
+ function: _+_
+ args: {
+ IDENT [21] {
+ name: @ac:1:0
+ }
+ LIST [22] {
+ elements: {
+ CALL [23] {
+ function: _+_
+ args: {
+ IDENT [24] {
+ name: @it:1:0
+ }
+ CONSTANT [25] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [26] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [27] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [28] {
+ function: _==_
+ args: {
+ IDENT [29] {
+ name: @index0
+ }
+ IDENT [30] {
+ name: @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]
=====>
@@ -2363,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: {
@@ -2384,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: {
@@ -2410,7 +2243,7 @@ CALL [1] {
function: _+_
args: {
IDENT [25] {
- name: @x:0
+ name: @ac:1:0
}
LIST [26] {
elements: {
@@ -2427,7 +2260,7 @@ CALL [1] {
}
result: {
IDENT [30] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2438,7 +2271,7 @@ CALL [1] {
}
result: {
IDENT [31] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2493,7 +2326,7 @@ CALL [1] {
function: _||_
args: {
COMPREHENSION [9] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [10] {
elements: {
@@ -2518,7 +2351,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [17] { value: false }
}
@@ -2530,7 +2363,7 @@ CALL [1] {
function: !_
args: {
IDENT [20] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2542,7 +2375,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
CALL [23] {
function: _>_
@@ -2551,7 +2384,7 @@ CALL [1] {
function: _-_
args: {
IDENT [25] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [26] { value: 1 }
}
@@ -2564,7 +2397,7 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2587,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
}
}
}
@@ -2598,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: {
@@ -2620,7 +2453,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [14] {
elements: {
@@ -2635,7 +2468,7 @@ CALL [1] {
function: _+_
args: {
IDENT [17] {
- name: @x:0
+ name: @ac:1:0
}
LIST [18] {
elements: {
@@ -2656,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: {
@@ -2676,7 +2509,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2697,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 d8c949600..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,59 +1266,75 @@ CALL [1] {
}
}
}
- LIST [63] {
- elements: {
- CONSTANT [64] { value: true }
- CONSTANT [65] { value: true }
- CONSTANT [66] { value: true }
- CONSTANT [67] { 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: {
- LIST [3] {
- elements: {
- CONSTANT [4] { value: 1 }
+ 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 }
}
}
- CALL [5] {
- function: _&&_
- args: {
- CALL [6] {
- function: _&&_
- args: {
- COMPREHENSION [7] {
- iter_var: @c:0
+ }
+}
+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: {
+ 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
}
}
}
@@ -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
}
}
}
@@ -2180,6 +1902,120 @@ 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: {
+ COMPREHENSION [3] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [4] {
+ elements: {
+ CONSTANT [5] { value: 1 }
+ CONSTANT [6] { value: 2 }
+ CONSTANT [7] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [8] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [9] { value: true }
+ }
+ loop_step: {
+ CALL [10] {
+ function: _+_
+ args: {
+ IDENT [11] {
+ name: @ac:0:0
+ }
+ LIST [12] {
+ elements: {
+ COMPREHENSION [13] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [14] {
+ elements: {
+ CONSTANT [15] { value: 1 }
+ CONSTANT [16] { value: 2 }
+ CONSTANT [17] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [18] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [19] { value: true }
+ }
+ loop_step: {
+ CALL [20] {
+ function: _+_
+ args: {
+ IDENT [21] {
+ name: @ac:1:0
+ }
+ LIST [22] {
+ elements: {
+ CALL [23] {
+ function: _+_
+ args: {
+ IDENT [24] {
+ name: @it:1:0
+ }
+ CONSTANT [25] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [26] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [27] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [28] {
+ function: _==_
+ args: {
+ IDENT [29] {
+ name: @index0
+ }
+ IDENT [30] {
+ name: @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]
=====>
@@ -2350,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: {
@@ -2371,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: {
@@ -2397,7 +2233,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:0
+ name: @ac:1:0
}
LIST [27] {
elements: {
@@ -2414,7 +2250,7 @@ CALL [1] {
}
result: {
IDENT [31] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2425,7 +2261,7 @@ CALL [1] {
}
result: {
IDENT [32] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2472,7 +2308,7 @@ CALL [1] {
function: _||_
args: {
COMPREHENSION [9] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [10] {
elements: {
@@ -2497,7 +2333,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [17] { value: false }
}
@@ -2509,7 +2345,7 @@ CALL [1] {
function: !_
args: {
IDENT [20] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2521,7 +2357,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
CALL [23] {
function: _>_
@@ -2530,7 +2366,7 @@ CALL [1] {
function: _-_
args: {
IDENT [25] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [26] { value: 1 }
}
@@ -2543,7 +2379,7 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2566,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
}
}
}
@@ -2577,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: {
@@ -2599,7 +2435,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [14] {
elements: {
@@ -2614,7 +2450,7 @@ CALL [1] {
function: _+_
args: {
IDENT [17] {
- name: @x:0
+ name: @ac:1:0
}
LIST [18] {
elements: {
@@ -2635,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: {
@@ -2655,7 +2491,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2676,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 b9bccc56c..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
- 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
}
}
}
@@ -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,59 +1254,75 @@ CALL [1] {
}
}
}
- LIST [63] {
- elements: {
- CONSTANT [64] { value: true }
- CONSTANT [65] { value: true }
- CONSTANT [66] { value: true }
- CONSTANT [67] { 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: {
- LIST [3] {
- elements: {
- CONSTANT [4] { value: 1 }
+ 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 }
}
}
- CALL [5] {
- function: _&&_
- args: {
- CALL [6] {
- function: _&&_
- args: {
- COMPREHENSION [7] {
- iter_var: @c:0
+ }
+}
+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: {
+ 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
}
}
}
@@ -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
}
}
}
@@ -2165,6 +1890,120 @@ 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: {
+ COMPREHENSION [3] {
+ iter_var: @it:0:0
+ iter_range: {
+ LIST [4] {
+ elements: {
+ CONSTANT [5] { value: 1 }
+ CONSTANT [6] { value: 2 }
+ CONSTANT [7] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:0:0
+ accu_init: {
+ LIST [8] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [9] { value: true }
+ }
+ loop_step: {
+ CALL [10] {
+ function: _+_
+ args: {
+ IDENT [11] {
+ name: @ac:0:0
+ }
+ LIST [12] {
+ elements: {
+ COMPREHENSION [13] {
+ iter_var: @it:1:0
+ iter_range: {
+ LIST [14] {
+ elements: {
+ CONSTANT [15] { value: 1 }
+ CONSTANT [16] { value: 2 }
+ CONSTANT [17] { value: 3 }
+ }
+ }
+ }
+ accu_var: @ac:1:0
+ accu_init: {
+ LIST [18] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [19] { value: true }
+ }
+ loop_step: {
+ CALL [20] {
+ function: _+_
+ args: {
+ IDENT [21] {
+ name: @ac:1:0
+ }
+ LIST [22] {
+ elements: {
+ CALL [23] {
+ function: _+_
+ args: {
+ IDENT [24] {
+ name: @it:1:0
+ }
+ CONSTANT [25] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [26] {
+ name: @ac:1:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [27] {
+ name: @ac:0:0
+ }
+ }
+ }
+ }
+ }
+ CALL [28] {
+ function: _==_
+ args: {
+ IDENT [29] {
+ name: @index0
+ }
+ IDENT [30] {
+ name: @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]
=====>
@@ -2335,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: {
@@ -2356,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: {
@@ -2382,7 +2221,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:0
+ name: @ac:1:0
}
LIST [27] {
elements: {
@@ -2399,7 +2238,7 @@ CALL [1] {
}
result: {
IDENT [31] {
- name: @x:0
+ name: @ac:1:0
}
}
}
@@ -2410,7 +2249,7 @@ CALL [1] {
}
result: {
IDENT [32] {
- name: @x:1
+ name: @ac:0:0
}
}
}
@@ -2457,7 +2296,7 @@ CALL [1] {
function: _||_
args: {
COMPREHENSION [9] {
- iter_var: @c:0
+ iter_var: @it:0:0
iter_range: {
LIST [10] {
elements: {
@@ -2482,7 +2321,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0:0
accu_init: {
CONSTANT [17] { value: false }
}
@@ -2494,7 +2333,7 @@ CALL [1] {
function: !_
args: {
IDENT [20] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2506,7 +2345,7 @@ CALL [1] {
function: _||_
args: {
IDENT [22] {
- name: @x:0
+ name: @ac:0:0
}
CALL [23] {
function: _>_
@@ -2515,7 +2354,7 @@ CALL [1] {
function: _-_
args: {
IDENT [25] {
- name: @c:0
+ name: @it:0:0
}
CONSTANT [26] { value: 1 }
}
@@ -2528,7 +2367,7 @@ CALL [1] {
}
result: {
IDENT [28] {
- name: @x:0
+ name: @ac:0:0
}
}
}
@@ -2551,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
}
}
}
@@ -2562,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: {
@@ -2584,7 +2423,7 @@ CALL [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:1:0
accu_init: {
LIST [14] {
elements: {
@@ -2599,7 +2438,7 @@ CALL [1] {
function: _+_
args: {
IDENT [17] {
- name: @x:0
+ name: @ac:1:0
}
LIST [18] {
elements: {
@@ -2620,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: {
@@ -2640,7 +2479,7 @@ CALL [1] {
function: _+_
args: {
IDENT [26] {
- name: @x:1
+ name: @ac:0:0
}
LIST [27] {
elements: {
@@ -2661,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 5d09067b9..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
}
}
}
@@ -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: @it:1
+ iter_range: {
+ IDENT [11] {
+ name: @r0
+ }
+ }
+ accu_var: @ac:1
+ accu_init: {
+ LIST [12] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [13] { value: true }
+ }
+ loop_step: {
+ CALL [14] {
+ function: _+_
+ args: {
+ IDENT [15] {
+ name: @ac:1
+ }
+ LIST [16] {
+ elements: {
+ COMPREHENSION [17] {
+ iter_var: @it:0
+ iter_range: {
+ IDENT [18] {
+ name: @r0
+ }
+ }
+ accu_var: @ac:0
+ accu_init: {
+ LIST [19] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [20] { value: true }
+ }
+ loop_step: {
+ CALL [21] {
+ function: _+_
+ args: {
+ IDENT [22] {
+ name: @ac:0
+ }
+ LIST [23] {
+ elements: {
+ CALL [24] {
+ function: _+_
+ args: {
+ IDENT [25] {
+ name: @it:0
+ }
+ CONSTANT [26] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [27] {
+ name: @ac:0
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [28] {
+ name: @ac:1
+ }
+ }
+ }
+ COMPREHENSION [29] {
+ iter_var: @it:3
+ iter_range: {
+ IDENT [30] {
+ name: @r0
+ }
+ }
+ accu_var: @ac:3
+ accu_init: {
+ LIST [31] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [32] { value: true }
+ }
+ loop_step: {
+ CALL [33] {
+ function: _+_
+ args: {
+ IDENT [34] {
+ name: @ac:3
+ }
+ LIST [35] {
+ elements: {
+ COMPREHENSION [36] {
+ iter_var: @it:2
+ iter_range: {
+ IDENT [37] {
+ name: @r0
+ }
+ }
+ accu_var: @ac:2
+ accu_init: {
+ LIST [38] {
+ elements: {
+ }
+ }
+ }
+ loop_condition: {
+ CONSTANT [39] { value: true }
+ }
+ loop_step: {
+ CALL [40] {
+ function: _+_
+ args: {
+ IDENT [41] {
+ name: @ac:2
+ }
+ LIST [42] {
+ elements: {
+ CALL [43] {
+ function: _+_
+ args: {
+ IDENT [44] {
+ name: @it:2
+ }
+ CONSTANT [45] { value: 1 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [46] {
+ name: @ac:2
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result: {
+ IDENT [47] {
+ name: @ac: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]
=====>
@@ -2934,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: {
@@ -2955,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: {
@@ -2981,7 +3184,7 @@ COMPREHENSION [1] {
function: _+_
args: {
IDENT [28] {
- name: @x:0
+ name: @ac:0
}
LIST [29] {
elements: {
@@ -2995,7 +3198,7 @@ COMPREHENSION [1] {
}
result: {
IDENT [31] {
- name: @x:0
+ name: @ac:0
}
}
}
@@ -3006,7 +3209,7 @@ COMPREHENSION [1] {
}
result: {
IDENT [32] {
- name: @x:1
+ name: @ac:1
}
}
}
@@ -3123,7 +3326,7 @@ COMPREHENSION [1] {
function: _||_
args: {
COMPREHENSION [16] {
- iter_var: @c:0
+ iter_var: @it:0
iter_range: {
LIST [17] {
elements: {
@@ -3142,7 +3345,7 @@ COMPREHENSION [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0
accu_init: {
CONSTANT [22] { value: false }
}
@@ -3154,7 +3357,7 @@ COMPREHENSION [1] {
function: !_
args: {
IDENT [25] {
- name: @x:0
+ name: @ac:0
}
}
}
@@ -3166,7 +3369,7 @@ COMPREHENSION [1] {
function: _||_
args: {
IDENT [27] {
- name: @x:0
+ name: @ac:0
}
CALL [28] {
function: _>_
@@ -3175,7 +3378,7 @@ COMPREHENSION [1] {
function: _-_
args: {
IDENT [30] {
- name: @c:0
+ name: @it:0
}
CONSTANT [31] { value: 1 }
}
@@ -3188,7 +3391,7 @@ COMPREHENSION [1] {
}
result: {
IDENT [33] {
- name: @x:0
+ name: @ac:0
}
}
}
@@ -3205,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: {
@@ -3217,7 +3420,7 @@ COMPREHENSION [1] {
}
}
}
- accu_var: @x:0
+ accu_var: @ac:0
accu_init: {
LIST [6] {
elements: {
@@ -3232,7 +3435,7 @@ COMPREHENSION [1] {
function: _+_
args: {
IDENT [9] {
- name: @x:0
+ name: @ac:0
}
LIST [10] {
elements: {
@@ -3250,10 +3453,10 @@ COMPREHENSION [1] {
function: _+_
args: {
IDENT [14] {
- name: @c:0
+ name: @it:0
}
IDENT [15] {
- name: @c:0
+ name: @it:0
}
}
}
@@ -3286,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: {
@@ -3306,7 +3509,7 @@ COMPREHENSION [1] {
function: _+_
args: {
IDENT [25] {
- name: @x:1
+ name: @ac:1
}
LIST [26] {
elements: {
@@ -3324,10 +3527,10 @@ COMPREHENSION [1] {
function: _+_
args: {
IDENT [30] {
- name: @c:1
+ name: @it:1
}
IDENT [31] {
- name: @c:1
+ name: @it:1
}
}
}
@@ -3360,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 831290039..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)
@@ -274,81 +291,103 @@ 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_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)
+[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_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])
+[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_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)
+[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_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])
+[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_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]])
+[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(@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)
+[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]
@@ -356,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)
@@ -372,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})
@@ -386,49 +427,52 @@ 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_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])
+[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_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)
+[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_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]))
+[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']
@@ -436,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"])
@@ -452,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)
@@ -468,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)
@@ -484,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)
@@ -500,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)
@@ -516,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)
@@ -532,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])
@@ -548,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")
@@ -564,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")
@@ -580,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)
@@ -596,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))
@@ -612,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"))
@@ -628,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"))
@@ -644,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"))
@@ -660,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))
@@ -676,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/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/main/java/dev/cel/policy/BUILD.bazel b/policy/src/main/java/dev/cel/policy/BUILD.bazel
index 15e2977c2..bdb651d0d 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",
],
@@ -256,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",
],
@@ -304,7 +309,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 4c39fee94..57914232f 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;
/**
@@ -28,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();
@@ -36,6 +42,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.isConditionTriviallyTrue()) {
+ 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.
@@ -59,10 +87,19 @@ 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 isConditionTriviallyTrue() {
+ 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 {
@@ -94,7 +131,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();
@@ -104,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 45a2c666c..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,11 @@ 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();
+
/** 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 {
@@ -186,13 +195,20 @@ 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);
public abstract Builder setResult(Result result);
+ public abstract Builder setExplanation(ValueString explanation);
+
+ abstract Optional id();
+
abstract Optional result();
+ abstract Optional explanation();
+
@Override
public ImmutableList requiredFields() {
return ImmutableList.of(RequiredField.of("output or a rule", this::result));
@@ -202,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/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 8ca38dad4..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;
@@ -35,10 +36,15 @@
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;
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;
@@ -51,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 {
@@ -66,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();
@@ -104,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();
@@ -167,10 +192,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() {
@@ -232,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
@@ -251,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);
}
}
@@ -263,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/main/java/dev/cel/policy/CelPolicyConfig.java b/policy/src/main/java/dev/cel/policy/CelPolicyConfig.java
index c5acc43f5..cf6ca3ec3 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();
@@ -365,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
@@ -470,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
@@ -482,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/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/CelPolicyYamlParser.java b/policy/src/main/java/dev/cel/policy/CelPolicyYamlParser.java
index 541dfdfb3..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);
@@ -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/main/java/dev/cel/policy/RuleComposer.java b/policy/src/main/java/dev/cel/policy/RuleComposer.java
index 732b60394..814dc8f8a 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;
@@ -52,7 +51,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);
@@ -75,17 +74,21 @@ 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.isConditionTriviallyTrue();
+
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());
if (isTriviallyTrue) {
matchAst = outAst;
isOptionalResult = false;
- lastOutputId = matchOutput.id();
+ lastOutputId = matchOutput.sourceId();
continue;
}
if (isOptionalResult) {
@@ -99,31 +102,49 @@ 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:
+ // 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 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 =
+ astMutator.newGlobalCall(
+ Operator.CONDITIONAL.getFunction(),
+ CelMutableAst.fromCelAst(conditionAst),
+ nestedRuleAst,
+ matchAst);
}
- matchAst = astMutator.newMemberCall(nestedRuleAst, Function.OR.getFunction(), matchAst);
+
assertComposedAstIsValid(
cel,
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/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/BUILD.bazel b/policy/src/test/java/dev/cel/policy/BUILD.bazel
index 8606ca254..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,7 +31,8 @@ java_library(
"//policy:validation_exception",
"//policy:value_string",
"//runtime",
- "@maven//:com_google_api_grpc_proto_google_common_protos",
+ "@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",
"@maven//:junit_junit",
diff --git a/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java b/policy/src/test/java/dev/cel/policy/CelPolicyCompilerImplTest.java
index 30915be4a..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;
@@ -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(
@@ -308,7 +344,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/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/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/java/dev/cel/policy/PolicyTestHelper.java b/policy/src/test/java/dev/cel/policy/PolicyTestHelper.java
index f323e5ca5..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,
@@ -87,7 +107,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/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'"
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
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
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
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/publish/cel_version.bzl b/publish/cel_version.bzl
index 96be40f81..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.6.0"
+CEL_VERSION = "0.7.1"
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/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
index f51706987..109e13d97 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",
],
@@ -135,6 +135,7 @@ RUNTIME_SOURCES = [
"CelRuntimeLegacyImpl.java",
"CelRuntimeLibrary.java",
"CelVariableResolver.java",
+ "HierarchicalVariableResolver.java",
"UnknownContext.java",
]
@@ -160,10 +161,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/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/main/java/dev/cel/runtime/StandardFunctions.java b/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java
index d7d00fdaa..c69c98271 100644
--- a/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java
+++ b/runtime/src/main/java/dev/cel/runtime/StandardFunctions.java
@@ -154,6 +154,35 @@ 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);
@@ -167,6 +196,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 +236,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 +278,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 +342,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 +540,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 +590,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 +759,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 +880,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/java/dev/cel/runtime/ActivationTest.java b/runtime/src/test/java/dev/cel/runtime/ActivationTest.java
index 5eb10737c..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;
@@ -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 =
diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
index fea8d6e43..0cafcda6b 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",
@@ -43,10 +40,12 @@ java_library(
"//runtime:runtime_helper",
"//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",
- "@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",
@@ -63,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",
],
)
@@ -79,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/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/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/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/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/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/boolConversions.baseline b/runtime/src/test/resources/boolConversions.baseline
new file mode 100644
index 000000000..2bc832baa
--- /dev/null
+++ b/runtime/src/test/resources/boolConversions.baseline
@@ -0,0 +1,26 @@
+Source: bool(true)
+=====>
+bindings: {}
+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/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/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/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/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/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/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/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 7e4c69fb9..5594c37be 100644
--- a/testing/src/main/java/dev/cel/testing/BUILD.bazel
+++ b/testing/src/main/java/dev/cel/testing/BUILD.bazel
@@ -75,63 +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",
- ],
-)
-
-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",
- "@maven//:com_google_guava_guava",
- "@maven//:com_google_protobuf_protobuf_java",
- ],
-)
-
-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",
- "@maven//:com_google_guava_guava",
- "@maven//:com_google_protobuf_protobuf_java",
- ],
-)
-
-java_library(
- name = "eval",
- testonly = 1,
- srcs = [
- "Eval.java",
- ],
- deps = [
- "//common",
- "//common:options",
- "//runtime:base",
- "//runtime:interpreter",
- "@maven//:com_google_errorprone_error_prone_annotations",
- "@maven//:com_google_guava_guava",
- "@maven//:com_google_protobuf_protobuf_java",
],
)
@@ -147,19 +93,19 @@ 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/resources/testdata/proto3:test_all_types_java_proto",
"//common/types:cel_types",
- "//runtime:interpreter",
+ "//runtime",
+ "//runtime:runtime_helper",
+ "@@protobuf~//java/core",
"@cel_spec//proto/cel/expr:expr_java_proto",
- "@maven//:com_google_errorprone_error_prone_annotations",
+ "@cel_spec//proto/test/v1/proto3:test_all_types_java_proto",
"@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/main/java/dev/cel/testing/BaseInterpreterTest.java b/testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java
index 795145508..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;
@@ -23,16 +24,19 @@
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;
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;
@@ -44,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;
@@ -56,27 +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 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;
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("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(
- 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,487 +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();
+
+ source = "timestamp(timestamp(123))"; // Identity
+ 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();
+
+ source = "uint(dyn(1u))"; // identity, check dynamic dispatch
+ 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();
}
@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();
}
@Test
@@ -1543,47 +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 bytesConversions() throws Exception {
+ public void boolConversions() {
+ source = "bool(true)";
+ runTest(); // Identity
+
+ source = "bool('true') && bool('TRUE') && bool('True') && bool('t') && bool('1')";
+ runTest(); // result is true
+
+ source = "bool('false') || bool('FALSE') || bool('False') || bool('f') || bool('0')";
+ runTest(); // result is false
+
+ source = "bool('TrUe')";
+ runTest(); // exception
+
+ source = "bool('FaLsE')";
+ runTest(); // exception
+ }
+
+ @Test
+ 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();
}
@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()));
@@ -1591,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 =
@@ -1611,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 =
@@ -1619,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 =
@@ -1636,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 =
@@ -1653,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.
@@ -1662,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.
@@ -1706,49 +1771,49 @@ 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 =
"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";
- runTest(Activation.EMPTY);
+ + "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();
// 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
@@ -1776,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{} && "
@@ -1789,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())
@@ -1805,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(
@@ -1819,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));
@@ -1843,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";
@@ -1859,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
@@ -1905,12 +1967,12 @@ 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();
- Activation activation =
- Activation.of(
+ ImmutableMap input =
+ ImmutableMap.of(
"msg",
DynamicMessage.parseFrom(
TestAllTypes.getDescriptor(),
@@ -1920,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.single_list_value";
- assertThat(runTest(activation)).isInstanceOf(List.class);
+ source = "msg.list_value";
+ assertThat(runTest(input)).isInstanceOf(List.class);
}
@Test
@@ -1972,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
@@ -2040,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(
@@ -2061,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/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));
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 4d4a12ec4..90cf73e3a 100644
--- a/testing/src/test/java/dev/cel/testing/BUILD.bazel
+++ b/testing/src/test/java/dev/cel/testing/BUILD.bazel
@@ -10,20 +10,8 @@ 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",
- "@maven//:com_google_api_grpc_proto_google_common_protos",
"@maven//:com_google_guava_guava",
- "@maven//:com_google_protobuf_protobuf_java",
"@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 e516d9780..000000000
--- a/testing/src/test/java/dev/cel/testing/EvalSyncTest.java
+++ /dev/null
@@ -1,184 +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.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), 1L},
- {UInt64Value.of(1), 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);
- }
- }
-}
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());
}
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 e9c07fb10..3362f14be 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",
],
)
@@ -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 eca252aa9..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,12 +17,14 @@ 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",
"@maven//:com_google_protobuf_protobuf_java_util",
"@maven//:com_google_testparameterinjector_test_parameter_injector",
"@maven//:junit_junit",
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"],
+)