Skip to content

Commit 415f166

Browse files
committed
Add variable disambiguation to prevent bdd confusion
1 parent 3f62010 commit 415f166

File tree

19 files changed

+1257
-231
lines changed

19 files changed

+1257
-231
lines changed

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/Template.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import software.amazon.smithy.rulesengine.language.evaluation.TypeCheck;
2323
import software.amazon.smithy.rulesengine.language.evaluation.type.Type;
2424
import software.amazon.smithy.rulesengine.language.syntax.ToExpression;
25-
import software.amazon.smithy.utils.SmithyBuilder;
2625
import software.amazon.smithy.utils.SmithyUnstableApi;
2726

2827
/**
@@ -41,7 +40,7 @@ public final class Template implements FromSourceLocation, ToNode {
4140
private final String value;
4241

4342
public Template(StringNode template) {
44-
sourceLocation = SmithyBuilder.requiredState("source", template.getSourceLocation());
43+
sourceLocation = template.getSourceLocation();
4544
value = template.getValue();
4645
parts = context("when parsing template", template, () -> parseTemplate(template.getValue(), template));
4746
}

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/functions/GetAttr.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import java.util.ArrayList;
1010
import java.util.List;
1111
import java.util.Objects;
12-
import java.util.Set;
1312
import software.amazon.smithy.model.FromSourceLocation;
1413
import software.amazon.smithy.model.node.ArrayNode;
1514
import software.amazon.smithy.model.node.Node;
@@ -155,11 +154,6 @@ public List<Part> getPath() {
155154
return path;
156155
}
157156

158-
@Override
159-
public Set<String> getReferences() {
160-
return getTarget().getReferences();
161-
}
162-
163157
@Override
164158
public <R> R accept(ExpressionVisitor<R> visitor) {
165159
return visitor.visitGetAttr(this);

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/functions/LibraryFunction.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package software.amazon.smithy.rulesengine.language.syntax.expressions.functions;
66

77
import java.util.ArrayList;
8-
import java.util.Collections;
98
import java.util.LinkedHashSet;
109
import java.util.List;
1110
import java.util.Objects;
@@ -54,7 +53,7 @@ public Set<String> getReferences() {
5453
for (Expression arg : getArguments()) {
5554
references.addAll(arg.getReferences());
5655
}
57-
return references.isEmpty() ? Collections.emptySet() : references;
56+
return references;
5857
}
5958

6059
/**

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/literal/RecordLiteral.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,6 @@ public Set<String> getReferences() {
8181
for (Literal value : members().values()) {
8282
references.addAll(value.getReferences());
8383
}
84-
return references.isEmpty() ? Collections.emptySet() : references;
84+
return references;
8585
}
8686
}

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/literal/StringLiteral.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public Set<String> getReferences() {
8383
references.addAll(((Template.Dynamic) part).toExpression().getReferences());
8484
}
8585
}
86-
return references.isEmpty() ? Collections.emptySet() : references;
86+
87+
return references;
8788
}
8889
}

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/expressions/literal/TupleLiteral.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package software.amazon.smithy.rulesengine.language.syntax.expressions.literal;
66

77
import java.util.ArrayList;
8-
import java.util.Collections;
98
import java.util.LinkedHashSet;
109
import java.util.List;
1110
import java.util.Objects;
@@ -88,6 +87,6 @@ public Set<String> getReferences() {
8887
for (Literal member : members()) {
8988
references.addAll(member.getReferences());
9089
}
91-
return references.isEmpty() ? Collections.emptySet() : references;
90+
return references;
9291
}
9392
}

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/language/syntax/rule/Rule.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ public Builder conditions(ToCondition... conditions) {
242242
return this;
243243
}
244244

245-
public Builder conditions(List<ToCondition> conditions) {
245+
public Builder conditions(List<? extends ToCondition> conditions) {
246246
this.conditions.addAll(conditions);
247247
return this;
248248
}
@@ -257,11 +257,15 @@ public EndpointRule endpoint(Endpoint endpoint) {
257257
}
258258

259259
public ErrorRule error(Node error) {
260-
return (ErrorRule) this.onBuild.apply(new ErrorRule(this, Expression.fromNode(error)));
260+
return error(Expression.fromNode(error));
261261
}
262262

263263
public ErrorRule error(String error) {
264-
return (ErrorRule) this.onBuild.apply(new ErrorRule(this, Literal.of(error)));
264+
return error(Literal.of(error));
265+
}
266+
267+
public ErrorRule error(Expression error) {
268+
return (ErrorRule) this.onBuild.apply(new ErrorRule(this, error));
265269
}
266270

267271
public TreeRule treeRule(Rule... rules) {

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/logic/bdd/Bdd.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@
3131
* <li>{@code -1}: FALSE terminal; represents boolean false, treated as "no match" in endpoint resolution</li>
3232
* <li>{@code 2, 3, ...}: Node references (points to nodes array at index ref-1)</li>
3333
* <li>{@code -2, -3, ...}: Complement node references (logical NOT of the referenced node)</li>
34-
* <li>{@code 2000000+}: Result terminals (2000000 + resultIndex)</li>
34+
* <li>{@code 100_000_000+}: Result terminals (100_000_000 + resultIndex)</li>
3535
* </ul>
3636
*
37-
* <p>Result terminals are encoded as special references starting at 2000000 (RESULT_OFFSET).
38-
* When evaluating the BDD, any reference >= 2000000 represents a result terminal that
39-
* indexes into the results array (resultIndex = ref - 2000000). These are not stored
37+
* <p>Result terminals are encoded as special references starting at 100_000_000 (RESULT_OFFSET).
38+
* When evaluating the BDD, any reference >= 100_000_000 represents a result terminal that
39+
* indexes into the results array (resultIndex = ref - 100_000_000). These are not stored
4040
* as nodes in the nodes array.
4141
*
4242
* <p><b>Node Format:</b> {@code [variable, high, low]}
@@ -50,9 +50,9 @@ public final class Bdd implements ToNode {
5050
/**
5151
* Result reference encoding.
5252
*
53-
* <p>Results start at 2M to avoid collision with node references.
53+
* <p>Results start at 100M to avoid collision with node references.
5454
*/
55-
public static final int RESULT_OFFSET = 2000000;
55+
public static final int RESULT_OFFSET = 100_000_000;
5656

5757
private final Parameters parameters;
5858
private final List<Condition> conditions;

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/logic/bdd/BddBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* <li>-1: FALSE terminal</li>
2525
* <li>2, 3, 4, ...: BDD nodes (use index + 1)</li>
2626
* <li>-2, -3, -4, ...: Complement of BDD nodes</li>
27-
* <li>Bdd.RESULT_OFFSET+: Result terminals (2000000 + resultIndex)</li>
27+
* <li>Bdd.RESULT_OFFSET+: Result terminals (100_000_000 + resultIndex)</li>
2828
* </ul>
2929
*
3030
* <p>Node storage format: [variableIndex, highRef, lowRef]

smithy-rules-engine/src/main/java/software/amazon/smithy/rulesengine/logic/bdd/BddNodeHelpers.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import software.amazon.smithy.model.node.ObjectNode;
1818
import software.amazon.smithy.rulesengine.language.syntax.parameters.Parameters;
1919
import software.amazon.smithy.rulesengine.language.syntax.rule.Condition;
20+
import software.amazon.smithy.rulesengine.language.syntax.rule.NoMatchRule;
2021
import software.amazon.smithy.rulesengine.language.syntax.rule.Rule;
2122
import software.amazon.smithy.utils.SetUtils;
2223

@@ -41,8 +42,15 @@ static Node toNode(Bdd bdd) {
4142
}
4243

4344
List<Node> results = new ArrayList<>();
44-
for (Rule r : bdd.getResults()) {
45-
results.add(r.toNode());
45+
if (!(bdd.getResults().get(0) instanceof NoMatchRule)) {
46+
throw new IllegalArgumentException("BDD must always have a NoMatchRule as the first result");
47+
}
48+
for (int i = 1; i < bdd.getResults().size(); i++) {
49+
Rule result = bdd.getResults().get(i);
50+
if (result instanceof NoMatchRule) {
51+
throw new IllegalArgumentException("NoMatch rules can only appear at rule index 0. Found at index" + i);
52+
}
53+
results.add(bdd.getResults().get(i).toNode());
4654
}
4755

4856
return builder
@@ -60,7 +68,13 @@ static Bdd fromNode(Node node) {
6068
obj.warnIfAdditionalProperties(ALLOWED_PROPERTIES);
6169
Parameters params = Parameters.fromNode(obj.expectObjectMember("parameters"));
6270
List<Condition> conditions = obj.expectArrayMember("conditions").getElementsAs(Condition::fromNode);
63-
List<Rule> results = obj.expectArrayMember("results").getElementsAs(Rule::fromNode);
71+
72+
// Read the results and prepend NoMatchRule at index 0
73+
List<Rule> serializedResults = obj.expectArrayMember("results").getElementsAs(Rule::fromNode);
74+
List<Rule> results = new ArrayList<>();
75+
results.add(NoMatchRule.INSTANCE); // Always add no-match at index 0
76+
results.addAll(serializedResults);
77+
6478
String nodesBase64 = obj.expectStringMember("nodes").getValue();
6579
int nodeCount = obj.expectNumberMember("nodeCount").getValue().intValue();
6680
int[][] nodes = decodeNodes(nodesBase64, nodeCount);

0 commit comments

Comments
 (0)