Skip to content

Commit d82c3d1

Browse files
committed
feat(codegen): Add BDD endpoint resolver code generation
Implement the BDD endpoint resolver code generation visitors that transform a Binary Decision Diagram into a Java endpoint provider. Code generation visitors: - BddEndpointProviderSpec: main spec emitting the provider class with nodeP/nodeN method dispatch — each BDD node becomes a method returning Endpoint directly (null = no match, throw = error) - BddResultCodeGeneratorVisitor: traverses the BDD node graph and emits node methods with condition checks and edge traversal - ConditionFnCodeGeneratorVisitor: emits condition evaluations (isSet, booleanEquals, stringEquals, function calls, getAttr) - ResultFnCodeGeneratorVisitor: emits endpoint construction and error results from BDD result nodes - AssignTypeInferringVisitor: infers types for BDD register variables from the condition/result expressions - RegistryInfo: metadata for BDD registers (name, type, index) Wiring: - EndpointProviderTasks: when EndpointBddModel is present, generate BddEndpointProvider instead of rules-based provider The generated resolver uses direct method dispatch per BDD node, with simple conditions inlined as ternary expressions for branch-predictor-friendly code paths.
1 parent bcb29c0 commit d82c3d1

13 files changed

Lines changed: 5316 additions & 1 deletion

File tree

codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/EndpointProviderTasks.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import software.amazon.awssdk.codegen.poet.rules.EndpointResolverUtilsSpec;
3636
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesClientTestSpec;
3737
import software.amazon.awssdk.codegen.poet.rules2.EndpointProviderSpec2;
38+
import software.amazon.awssdk.codegen.poet.rules2.bdd.BddEndpointProviderSpec;
3839

3940
public final class EndpointProviderTasks extends BaseGeneratorTasks {
4041
private final GeneratorTaskParams generatorTaskParams;
@@ -50,7 +51,11 @@ protected List<GeneratorTask> createTasks() throws Exception {
5051
tasks.add(generateInterface());
5152
tasks.add(generateParams());
5253
if (shouldGenerateCompiledEndpointRules()) {
53-
tasks.add(generateDefaultProvider2());
54+
if (generatorTaskParams.getModel().getEndpointBddModel() != null) {
55+
tasks.add(generateDefaultProviderBdd());
56+
} else {
57+
tasks.add(generateDefaultProvider2());
58+
}
5459
tasks.add(new RulesEngineRuntimeLiteGeneratorTask(generatorTaskParams));
5560
tasks.add(new RulesEngineRuntimeGeneratorTask2(generatorTaskParams));
5661
} else {
@@ -90,6 +95,14 @@ private GeneratorTask generateDefaultProvider2() {
9095
return new PoetGeneratorTask(endpointRulesInternalDir(), model.getFileHeader(), new EndpointProviderSpec2(model));
9196
}
9297

98+
private GeneratorTask generateDefaultProviderBdd() {
99+
return new PoetGeneratorTask(
100+
endpointRulesInternalDir(),
101+
model.getFileHeader(),
102+
new BddEndpointProviderSpec(model)
103+
);
104+
}
105+
93106
private GeneratorTask generateDefaultPartitionsProvider() {
94107
return new PoetGeneratorTask(endpointRulesInternalDir(), model.getFileHeader(),
95108
new DefaultPartitionDataProviderSpec(model));
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.codegen.poet.rules2.bdd;
17+
18+
import java.util.Map;
19+
import software.amazon.awssdk.codegen.poet.rules2.BooleanAndExpression;
20+
import software.amazon.awssdk.codegen.poet.rules2.BooleanNotExpression;
21+
import software.amazon.awssdk.codegen.poet.rules2.EndpointExpression;
22+
import software.amazon.awssdk.codegen.poet.rules2.ErrorExpression;
23+
import software.amazon.awssdk.codegen.poet.rules2.FunctionCallExpression;
24+
import software.amazon.awssdk.codegen.poet.rules2.HeadersExpression;
25+
import software.amazon.awssdk.codegen.poet.rules2.IndexedAccessExpression;
26+
import software.amazon.awssdk.codegen.poet.rules2.LetExpression;
27+
import software.amazon.awssdk.codegen.poet.rules2.ListExpression;
28+
import software.amazon.awssdk.codegen.poet.rules2.LiteralBooleanExpression;
29+
import software.amazon.awssdk.codegen.poet.rules2.LiteralIntegerExpression;
30+
import software.amazon.awssdk.codegen.poet.rules2.LiteralStringExpression;
31+
import software.amazon.awssdk.codegen.poet.rules2.MemberAccessExpression;
32+
import software.amazon.awssdk.codegen.poet.rules2.MethodCallExpression;
33+
import software.amazon.awssdk.codegen.poet.rules2.PropertiesExpression;
34+
import software.amazon.awssdk.codegen.poet.rules2.RuleExpression;
35+
import software.amazon.awssdk.codegen.poet.rules2.RuleExpressionVisitor;
36+
import software.amazon.awssdk.codegen.poet.rules2.RuleFunctionMirror;
37+
import software.amazon.awssdk.codegen.poet.rules2.RuleRuntimeTypeMirror;
38+
import software.amazon.awssdk.codegen.poet.rules2.RuleSetExpression;
39+
import software.amazon.awssdk.codegen.poet.rules2.RuleType;
40+
import software.amazon.awssdk.codegen.poet.rules2.StringConcatExpression;
41+
import software.amazon.awssdk.codegen.poet.rules2.VariableReferenceExpression;
42+
43+
public class AssignTypeInferringVisitor implements RuleExpressionVisitor<RuleType> {
44+
private final RuleRuntimeTypeMirror typeMirror;
45+
private final Map<String, RegistryInfo> registerInfoMap;
46+
47+
public AssignTypeInferringVisitor(RuleRuntimeTypeMirror typeMirror, Map<String, RegistryInfo> registerInfoMap) {
48+
this.typeMirror = typeMirror;
49+
this.registerInfoMap = registerInfoMap;
50+
}
51+
52+
@Override
53+
public RuleType visitLiteralBooleanExpression(LiteralBooleanExpression e) {
54+
return RuleRuntimeTypeMirror.BOOLEAN;
55+
}
56+
57+
@Override
58+
public RuleType visitLiteralIntegerExpression(LiteralIntegerExpression e) {
59+
return RuleRuntimeTypeMirror.INTEGER;
60+
}
61+
62+
@Override
63+
public RuleType visitLiteralStringExpression(LiteralStringExpression e) {
64+
return RuleRuntimeTypeMirror.STRING;
65+
}
66+
67+
@Override
68+
public RuleType visitBooleanNotExpression(BooleanNotExpression e) {
69+
return RuleRuntimeTypeMirror.BOOLEAN;
70+
}
71+
72+
@Override
73+
public RuleType visitBooleanAndExpression(BooleanAndExpression e) {
74+
return RuleRuntimeTypeMirror.BOOLEAN;
75+
}
76+
77+
@Override
78+
public RuleType visitFunctionCallExpression(FunctionCallExpression e) {
79+
String fn = e.name();
80+
if ("not".equals(fn)) {
81+
return RuleRuntimeTypeMirror.BOOLEAN;
82+
}
83+
if ("isSet".equals(fn)) {
84+
return RuleRuntimeTypeMirror.BOOLEAN;
85+
}
86+
if ("isNotSet".equals(fn)) {
87+
return RuleRuntimeTypeMirror.BOOLEAN;
88+
}
89+
RuleFunctionMirror func = typeMirror.resolveFunction(e.name());
90+
return func.returns();
91+
}
92+
93+
@Override
94+
public RuleType visitMethodCallExpression(MethodCallExpression e) {
95+
throw new IllegalStateException("Unexpected methodCallExpression");
96+
}
97+
98+
@Override
99+
public RuleType visitVariableReferenceExpression(VariableReferenceExpression e) {
100+
RuleType type = registerInfoMap.get(e.variableName()).getRuleType();
101+
if (type == null) {
102+
// visit the assign condition for this
103+
registerInfoMap.get(e.variableName()).getRuleSetExpression().accept(this);
104+
type = registerInfoMap.get(e.variableName()).getRuleType();
105+
if (type == null) {
106+
throw new IllegalStateException("Unable to infer registry type information for `" + e.variableName() + "`");
107+
}
108+
}
109+
return type;
110+
}
111+
112+
@Override
113+
public RuleType visitMemberAccessExpression(MemberAccessExpression e) {
114+
RuleType sourceType = e.source().accept(this);
115+
if (e.directIndex() && e.name() == null) {
116+
return sourceType;
117+
}
118+
return sourceType.property(e.name());
119+
}
120+
121+
@Override
122+
public RuleType visitIndexedAccessExpression(IndexedAccessExpression e) {
123+
RuleType sourceType = e.source().accept(this);
124+
return sourceType.ruleTypeParam(); // get the list inner type
125+
}
126+
127+
@Override
128+
public RuleType visitStringConcatExpression(StringConcatExpression e) {
129+
return RuleRuntimeTypeMirror.STRING;
130+
}
131+
132+
@Override
133+
public RuleType visitLetExpression(LetExpression e) {
134+
if (e.bindings().size() != 1) {
135+
throw new IllegalStateException("Expected exactly one binding");
136+
}
137+
for (Map.Entry<String, RuleExpression> kvp : e.bindings().entrySet()) {
138+
String k = kvp.getKey();
139+
RuleExpression v = kvp.getValue();
140+
RuleType assignedType = v.accept(this);
141+
registerInfoMap.get(k).setRuleType(assignedType);
142+
}
143+
return RuleRuntimeTypeMirror.BOOLEAN;
144+
}
145+
146+
@Override
147+
public RuleType visitRuleSetExpression(RuleSetExpression e) {
148+
if (e.conditions().size() != 1) {
149+
throw new IllegalStateException("Expected exactly one condition");
150+
}
151+
e.conditions().get(0).accept(this);
152+
return RuleRuntimeTypeMirror.VOID;
153+
}
154+
155+
@Override
156+
public RuleType visitListExpression(ListExpression e) {
157+
// TODO: this could potentially be another type
158+
return RuleRuntimeTypeMirror.LIST_OF_STRING;
159+
}
160+
161+
@Override
162+
public RuleType visitEndpointExpression(EndpointExpression e) {
163+
throw new IllegalStateException("Unexpected EndpointExpression");
164+
}
165+
166+
@Override
167+
public RuleType visitErrorExpression(ErrorExpression e) {
168+
throw new IllegalStateException("Unexpected ErrorExpression");
169+
}
170+
171+
@Override
172+
public RuleType visitPropertiesExpression(PropertiesExpression e) {
173+
throw new IllegalStateException("Unexpected PropertiesExpression");
174+
}
175+
176+
@Override
177+
public RuleType visitHeadersExpression(HeadersExpression e) {
178+
throw new IllegalStateException("Unexpected HeadersExpression");
179+
}
180+
}

0 commit comments

Comments
 (0)