Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Positional trait support in Go codegen #665

Draft
wants to merge 8 commits into
base: Golang/dev
Choose a base branch
from
Draft
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
5 changes: 5 additions & 0 deletions TestModels/Positional/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,8 @@ INDEX_FILE_WITHOUT_EXTERN_STRING="module SimplePositional refines AbstractSimple
WRAPPED_INDEX_FILE_PATH=src/WrappedSimplePositionalImpl.dfy
WRAPPED_INDEX_FILE_WITH_EXTERN_STRING="module {:options \"--function-syntax:4\"} {:extern \"simple.positional.internaldafny.wrapped\"} WrappedSimplePositionalService refines WrappedAbstractSimplePositionalService {"
WRAPPED_INDEX_FILE_WITHOUT_EXTERN_STRING="module {:options \"--function-syntax:4\"} WrappedSimplePositionalService refines WrappedAbstractSimplePositionalService {"

GO_MODULE_NAME="github.com/smithy-lang/smithy-dafny/TestModels/Positional"

TRANSLATION_RECORD_GO := \
dafny-dependencies/StandardLibrary/runtimes/go/ImplementationFromDafny-go/ImplementationFromDafny-go.dtr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/smithy-lang/smithy-dafny/TestModels/Positional

go 1.23.0

require (
github.com/dafny-lang/DafnyRuntimeGo/v4 v4.8.0
github.com/dafny-lang/DafnyStandardLibGo v0.0.0
)

replace github.com/dafny-lang/DafnyStandardLibGo => ../../../../dafny-dependencies/StandardLibrary/runtimes/go/ImplementationFromDafny-go/
14 changes: 14 additions & 0 deletions TestModels/Positional/runtimes/go/TestsFromDafny-go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/smithy-lang/smithy-dafny/TestModels/Positional/test

go 1.23.0

require github.com/dafny-lang/DafnyStandardLibGo v0.0.0

require (
github.com/dafny-lang/DafnyRuntimeGo/v4 v4.8.0
github.com/smithy-lang/smithy-dafny/TestModels/Positional v0.0.0
)

replace github.com/smithy-lang/smithy-dafny/TestModels/Positional v0.0.0 => ../ImplementationFromDafny-go

replace github.com/dafny-lang/DafnyStandardLibGo => ../../../../dafny-dependencies/StandardLibrary/runtimes/go/ImplementationFromDafny-go/
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ class GoTestModels extends TestModelTest {
DISABLED_TESTS.add("MultipleModels");
DISABLED_TESTS.add("LocalService");

//TODO: Pending PR Merge
DISABLED_TESTS.add("Positional");

//V1 Tests are not supported in Go
DISABLED_TESTS.add("aws-sdks/ddb");
DISABLED_TESTS.add("aws-sdks/kms");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import software.amazon.polymorph.smithygo.localservice.nameresolver.SmithyNameResolver;
import software.amazon.polymorph.traits.ExtendableTrait;
import software.amazon.polymorph.traits.LocalServiceTrait;
import software.amazon.polymorph.traits.PositionalTrait;
import software.amazon.polymorph.traits.ReferenceTrait;
import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.TopDownIndex;
Expand Down Expand Up @@ -212,7 +214,7 @@ func NewClient(clientConfig $L) (*$T, error) {
SmithyNameResolver.smithyTypesNamespace(inputShape),
inputShape.toShapeId().getName()
);
final var outputType = outputShape.hasTrait(UnitTypeTrait.class)
var outputType = outputShape.hasTrait(UnitTypeTrait.class)
? ""
: "*%s.%s,".formatted(
SmithyNameResolver.smithyTypesNamespace(outputShape),
Expand Down Expand Up @@ -241,15 +243,38 @@ func NewClient(clientConfig $L) (*$T, error) {
operationShape.getId().getName()
);
} else {
String dafnyType;
if (inputShape.hasTrait(PositionalTrait.class)) {
Shape inputForPositional = model.expectShape(
inputShape
.getAllMembers()
.values()
.stream()
.findFirst()
.get()
.getTarget()
);
Symbol symbolForPositional = symbolProvider.toSymbol(
inputForPositional
);
dafnyType =
DafnyNameResolver.getDafnyType(
inputForPositional,
symbolForPositional
);
} else {
dafnyType =
DafnyNameResolver.getDafnyType(
inputShape,
symbolProvider.toSymbol(inputShape)
);
}
baseClientCall =
"""
var dafny_request %s = %s(params)
var dafny_response = client.DafnyClient.%s(dafny_request)
""".formatted(
DafnyNameResolver.getDafnyType(
inputShape,
symbolProvider.toSymbol(inputShape)
),
dafnyType,
SmithyNameResolver.getToDafnyMethodName(
service,
inputShape,
Expand All @@ -264,21 +289,30 @@ func NewClient(clientConfig $L) (*$T, error) {
returnResponse = "return nil";
returnError = "return";
} else {
returnResponse =
"""
var native_response = %s(dafny_response.Extract().(%s))
return &native_response, nil
""".formatted(
SmithyNameResolver.getFromDafnyMethodName(
service,
outputShape,
""
),
DafnyNameResolver.getDafnyType(
outputShape,
symbolProvider.toSymbol(outputShape)
)
);
if (outputShape.hasTrait(PositionalTrait.class)) {
outputType = "interface{},";
returnResponse =
"""
var native_response = dafny_response.Extract()
return native_response, nil
""";
} else {
returnResponse =
"""
var native_response = %s(dafny_response.Extract().(%s))
return &native_response, nil
""".formatted(
SmithyNameResolver.getFromDafnyMethodName(
service,
outputShape,
""
),
DafnyNameResolver.getDafnyType(
outputShape,
symbolProvider.toSymbol(outputShape)
)
);
}
returnError = "return nil,";
}

Expand Down Expand Up @@ -396,15 +430,16 @@ void generateShim() {
final var outputShape = model.expectShape(
operationShape.getOutputShape()
);
final var inputType = inputShape.hasTrait(UnitTypeTrait.class)
// this is maybe because positional trait can change this
final var maybeInputType = inputShape.hasTrait(UnitTypeTrait.class)
? ""
: "input %s".formatted(
DafnyNameResolver.getDafnyType(
inputShape,
symbolProvider.toSymbol(inputShape)
)
);

final String inputType;
final var typeConversion = inputShape.hasTrait(UnitTypeTrait.class)
? ""
: "var native_request = %s(input)".formatted(
Expand Down Expand Up @@ -434,6 +469,32 @@ void generateShim() {
SmithyNameResolver.getToDafnyMethodName(outputShape, "")
);
}
if (inputShape.hasTrait(PositionalTrait.class)) {
writer.addImportFromModule(
"github.com/dafny-lang/DafnyRuntimeGo",
"dafny"
);
Shape inputForPositional = model.expectShape(
inputShape
.getAllMembers()
.values()
.stream()
.findFirst()
.get()
.getTarget()
);
Symbol symbolForPositional = symbolProvider.toSymbol(
inputForPositional
);
String dafnyType = DafnyNameResolver.getDafnyType(
inputForPositional,
symbolForPositional
);
inputType = "input %s".formatted(dafnyType);
returnResponse = "(native_response)";
} else {
inputType = maybeInputType;
}

writer.write(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
import software.amazon.polymorph.smithygo.utils.GoCodegenUtils;
import software.amazon.polymorph.traits.ExtendableTrait;
import software.amazon.polymorph.traits.LocalServiceTrait;
import software.amazon.polymorph.traits.PositionalTrait;
import software.amazon.polymorph.traits.ReferenceTrait;
import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.ResourceShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.traits.ErrorTrait;
Expand Down Expand Up @@ -78,6 +81,29 @@ public void generateSerializers(final GenerationContext context) {
final var inputToDafnyMethodName =
SmithyNameResolver.getToDafnyMethodName(serviceShape, input, "");
final var inputSymbol = symbolProvider.toSymbol(input);
final String outputType;
if (input.hasTrait(PositionalTrait.class)) {
// Output type in To Dafny should be unwrapped
Shape inputForPositional = model.expectShape(
input
.getAllMembers()
.values()
.stream()
.findFirst()
.get()
.getTarget()
);
Symbol symbolForPositional = symbolProvider.toSymbol(
inputForPositional
);
outputType =
DafnyNameResolver.getDafnyType(
inputForPositional,
symbolForPositional
);
} else {
outputType = DafnyNameResolver.getDafnyType(input, inputSymbol);
}
writerDelegator.useFileWriter(
"%s/%s".formatted(
SmithyNameResolver.shapeNamespace(serviceShape),
Expand All @@ -98,7 +124,7 @@ public void generateSerializers(final GenerationContext context) {
}""",
inputToDafnyMethodName,
SmithyNameResolver.getSmithyType(input, inputSymbol),
DafnyNameResolver.getDafnyType(input, inputSymbol),
outputType,
writer.consumer(w ->
generateRequestSerializer(
context,
Expand All @@ -113,7 +139,10 @@ public void generateSerializers(final GenerationContext context) {
}

final var output = model.expectShape(operation.getOutputShape());
if (!alreadyVisited.contains(output.toShapeId())) {
if (
!alreadyVisited.contains(output.toShapeId()) &&
!output.hasTrait(PositionalTrait.class)
) {
alreadyVisited.add(output.toShapeId());
if (
!output.hasTrait(UnitTypeTrait.class) &&
Expand Down Expand Up @@ -370,6 +399,31 @@ public void generateDeserializers(final GenerationContext context) {
""
);
final var inputSymbol = context.symbolProvider().toSymbol(input);
final String inputType;
if (input.hasTrait(PositionalTrait.class)) {
// Input type in To native should be unwrapped
Shape inputForPositional = context
.model()
.expectShape(
input
.getAllMembers()
.values()
.stream()
.findFirst()
.get()
.getTarget()
);
Symbol symbolForPositional = context
.symbolProvider()
.toSymbol(inputForPositional);
inputType =
DafnyNameResolver.getDafnyType(
inputForPositional,
symbolForPositional
);
} else {
inputType = DafnyNameResolver.getDafnyType(input, inputSymbol);
}
delegator.useFileWriter(
"%s/%s".formatted(
SmithyNameResolver.shapeNamespace(serviceShape),
Expand All @@ -390,7 +444,7 @@ public void generateDeserializers(final GenerationContext context) {
${C|}
}""",
inputFromDafnyMethodName,
DafnyNameResolver.getDafnyType(input, inputSymbol),
inputType,
SmithyNameResolver.getSmithyType(input, inputSymbol),
writer.consumer(w ->
generateRequestDeserializer(
Expand All @@ -408,7 +462,10 @@ public void generateDeserializers(final GenerationContext context) {
final var output = context
.model()
.expectShape(operation.getOutputShape());
if (!alreadyVisited.contains(output.toShapeId())) {
if (
!alreadyVisited.contains(output.toShapeId()) &&
!output.hasTrait(PositionalTrait.class)
) {
alreadyVisited.add(output.toShapeId());
if (
!output.hasTrait(UnitTypeTrait.class) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import software.amazon.polymorph.smithygo.localservice.nameresolver.SmithyNameResolver;
import software.amazon.polymorph.smithygo.utils.GoCodegenUtils;
import software.amazon.polymorph.traits.DafnyUtf8BytesTrait;
import software.amazon.polymorph.traits.PositionalTrait;
import software.amazon.polymorph.traits.ReferenceTrait;
import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.codegen.core.CodegenException;
Expand Down Expand Up @@ -276,6 +277,13 @@ public String structureShape(final StructureShape shape) {
final var targetShape = context
.model()
.expectShape(memberShape.getTarget());
final String DtorConversion;
if (!shape.hasTrait(PositionalTrait.class)) {
DtorConversion = ".Dtor_%s()".formatted(memberName);
} else {
// Shapes with PositionalTrait already gets input unwrapped so no conversion needed.
DtorConversion = "";
}
//TODO: Is it ever possible for structure to be nil?
String maybeAssertion = "";
if (dataSource.equals("input")) {
Expand All @@ -296,7 +304,7 @@ public String structureShape(final StructureShape shape) {
"%1$s%2$s%3$s%4$s%5$s".formatted(
dataSource,
maybeAssertion,
".Dtor_%s()".formatted(memberName),
DtorConversion,
memberShape.isOptional() ? ".UnwrapOr(nil)" : "",
assertionRequired
? ".(%s)".formatted(
Expand Down
Loading
Loading