Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,10 +57,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
Expand DownExpand Up@@ -121,8 +119,7 @@ public static SubexpressionOptimizer newInstance(SubexpressionOptimizerOptions c

@Override
public OptimizationResult optimize(CelAbstractSyntaxTree ast, Cel cel) {
OptimizationResult result =
cseOptions.enableCelBlock() ? optimizeUsingCelBlock(ast, cel) : optimizeUsingCelBind(ast);
OptimizationResult result = optimizeUsingCelBlock(ast, cel);

verifyOptimizedAstCorrectness(result.optimizedAst());

Expand DownExpand Up@@ -330,123 +327,8 @@ private static ImmutableList<CelVarDecl> newBlockIndexVariableDeclarations(
return varDeclBuilder.build();
}

private OptimizationResult optimizeUsingCelBind(CelAbstractSyntaxTree ast) {
CelMutableAst astToModify = CelMutableAst.fromCelAst(ast);
if (!cseOptions.populateMacroCalls()) {
astToModify.source().clearMacroCalls();
}

astToModify =
astMutator
.mangleComprehensionIdentifierNames(
astToModify,
MANGLED_COMPREHENSION_ITER_VAR_PREFIX,
MANGLED_COMPREHENSION_ACCU_VAR_PREFIX,
/* incrementSerially= */ true)
.mutableAst();
CelMutableSource sourceToModify = astToModify.source();

int bindIdentifierIndex = 0;
int iterCount;
for (iterCount = 0; iterCount < cseOptions.iterationLimit(); iterCount++) {
CelNavigableMutableAst navAst = CelNavigableMutableAst.fromAst(astToModify);
List<CelMutableExpr> cseCandidates = getCseCandidates(navAst);
if (cseCandidates.isEmpty()) {
break;
}

String bindIdentifier = BIND_IDENTIFIER_PREFIX + bindIdentifierIndex;
bindIdentifierIndex++;

// Replace all CSE candidates with new bind identifier
for (CelMutableExpr cseCandidate : cseCandidates) {
iterCount++;

astToModify =
astMutator.replaceSubtree(
astToModify, CelMutableExpr.ofIdent(bindIdentifier), cseCandidate.id());
}

// Find LCA to insert the new cel.bind macro into.
CelNavigableMutableExpr lca = getLca(navAst, bindIdentifier);

// Insert the new bind call
CelMutableExpr subexpressionToBind = cseCandidates.get(0);
// Re-add the macro source for bind identifiers that might have been lost from previous
// iteration of CSE
astToModify.source().addAllMacroCalls(sourceToModify.getMacroCalls());
astToModify =
astMutator.replaceSubtreeWithNewBindMacro(
astToModify,
bindIdentifier,
subexpressionToBind,
lca.expr(),
lca.id(),
cseOptions.populateMacroCalls());

// Retain the existing macro calls in case if the bind identifiers are replacing a subtree
// that contains a comprehension.
sourceToModify = astToModify.source();
}

if (iterCount >= cseOptions.iterationLimit()) {
throw new IllegalStateException("Max iteration count reached.");
}

if (iterCount == 0) {
// No modification has been made.
return OptimizationResult.create(ast);
}

astToModify = astMutator.renumberIdsConsecutively(astToModify);

return OptimizationResult.create(astToModify.toParsedAst());
}

private static CelNavigableMutableExpr getLca(
CelNavigableMutableAst navAst, String boundIdentifier) {
CelNavigableMutableExpr root = navAst.getRoot();
ImmutableList<CelNavigableMutableExpr> allNodesWithIdentifier =
root.allNodes()
.filter(
node ->
node.getKind().equals(Kind.IDENT)
&& node.expr().ident().name().equals(boundIdentifier))
.collect(toImmutableList());

if (allNodesWithIdentifier.size() < 2) {
throw new IllegalStateException("Expected at least 2 bound identifiers to be present.");
}

CelNavigableMutableExpr lca = root;
long lcaAncestorCount = 0;
HashMap<Long, Long> ancestors = new HashMap<>();
for (CelNavigableMutableExpr navigableExpr : allNodesWithIdentifier) {
Optional<CelNavigableMutableExpr> maybeParent = Optional.of(navigableExpr);
while (maybeParent.isPresent()) {
CelNavigableMutableExpr parent = maybeParent.get();
if (!ancestors.containsKey(parent.id())) {
ancestors.put(parent.id(), 1L);
continue;
}

long ancestorCount = ancestors.get(parent.id());
if (lcaAncestorCount < ancestorCount
|| (lcaAncestorCount == ancestorCount && lca.depth() < parent.depth())) {
lca = parent;
lcaAncestorCount = ancestorCount;
}

ancestors.put(parent.id(), ancestorCount + 1);
maybeParent = parent.parent();
}
}

return lca;
}

private List<CelMutableExpr> getCseCandidates(CelNavigableMutableAst navAst) {
if (cseOptions.enableCelBlock() && cseOptions.subexpressionMaxRecursionDepth() > 0) {
if (cseOptions.subexpressionMaxRecursionDepth() > 0) {
return getCseCandidatesWithRecursionDepth(
navAst, cseOptions.subexpressionMaxRecursionDepth());
} else {
Expand DownExpand Up@@ -689,11 +571,9 @@ public abstract static class Builder {
public abstract Builder populateMacroCalls(boolean value);

/**
* Rewrites the optimized AST using cel.@block call instead of cascaded cel.bind macros, aimed
* to produce a more compact AST. {@link CelSource.Extension} field will be populated in the
* AST to inform that special runtime support is required to evaluate the optimized
* expression.
* @deprecated This option is a no-op. cel.@block is always enabled.
*/
@Deprecated
public abstract Builder enableCelBlock(boolean value);

/**
Expand All@@ -708,9 +588,8 @@ public abstract static class Builder {
* <p>Note that expressions containing no common subexpressions may become a candidate for
* extraction to satisfy the max depth requirement.
*
* <p>This is a no-op if {@link #enableCelBlock} is set to false, the configured value is less
* than 1, or no subexpression needs to be extracted because the entire expression is already
* under the designated limit.
* <p>This is a no-op if the configured value is less than 1, or no subexpression needs to be
* extracted because the entire expression is already under the designated limit.
*
* <p>Examples:
*
Expand DownExpand Up@@ -756,8 +635,8 @@ public Builder addEliminableFunctions(String... functions) {
public static Builder newBuilder() {
return new AutoValue_SubexpressionOptimizer_SubexpressionOptimizerOptions.Builder()
.iterationLimit(500)
.enableCelBlock(true)
.populateMacroCalls(false)
.enableCelBlock(false)
.subexpressionMaxRecursionDepth(0);
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -73,7 +73,6 @@ public class SubexpressionOptimizerBaselineTest extends BaselineTestCase {
private static final SubexpressionOptimizerOptions OPTIMIZER_COMMON_OPTIONS =
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.addEliminableFunctions("pure_custom_func")
.build();

Expand DownExpand Up@@ -187,28 +186,11 @@ public void subexpression_ast(@TestParameter CseTestOptimizer cseTestOptimizer)
}
}

@Test
public void large_expressions_bind_cascaded() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(false)
.build());

runLargeTestCases(celOptimizer);
}

@Test
public void large_expressions_block_common_subexpr() throws Exception {
CelOptimizer celOptimizer =
newCseOptimizer(
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.build());
CEL, SubexpressionOptimizerOptions.newBuilder().populateMacroCalls(true).build());

runLargeTestCases(celOptimizer);
}
Expand All@@ -220,7 +202,6 @@ public void large_expressions_block_recursion_depth_1() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(1)
.build());

Expand All@@ -234,7 +215,6 @@ public void large_expressions_block_recursion_depth_2() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(2)
.build());

Expand All@@ -248,7 +228,6 @@ public void large_expressions_block_recursion_depth_3() throws Exception {
CEL,
SubexpressionOptimizerOptions.newBuilder()
.populateMacroCalls(true)
.enableCelBlock(true)
.subexpressionMaxRecursionDepth(3)
.build());

Expand DownExpand Up@@ -312,7 +291,6 @@ private static CelOptimizer newCseOptimizer(Cel cel, SubexpressionOptimizerOptio

@SuppressWarnings("Immutable") // Test only
private enum CseTestOptimizer {
CASCADED_BINDS(OPTIMIZER_COMMON_OPTIONS.toBuilder().enableCelBlock(false).build()),
BLOCK_COMMON_SUBEXPR_ONLY(OPTIMIZER_COMMON_OPTIONS),
BLOCK_RECURSION_DEPTH_1(
OPTIMIZER_COMMON_OPTIONS.toBuilder().subexpressionMaxRecursionDepth(1).build()),
Expand Down
Loading