summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java10
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java6
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java281
3 files changed, 230 insertions, 67 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java
index c956e2c..f747e44 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java
@@ -14,16 +14,6 @@ public record TypedStructDefinitionNode(
DocComment docComment,
Source source
) implements TypedNamespaceStatementNode {
- public SimpleStructType typeOrThrow() {
- return switch (typeOrConstructor) {
- case TypeOrConstructor.Constructor<SimpleStructType> constructor ->
- throw new UnsupportedOperationException("TODO");
-
- case TypeOrConstructor.Type<SimpleStructType> type ->
- type.value();
- };
- }
-
public String name() {
return this.typeOrConstructor.name();
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java
index c1310f1..be42c08 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java
@@ -358,7 +358,7 @@ public class JavaTransient0Generator implements Generator {
}
private JavaMethodDeclaration generateEncodeIntMethod(
- Type type,
+ SimpleType type,
int bits
) {
var statements = byteIndicesInBits(bits)
@@ -695,7 +695,7 @@ public class JavaTransient0Generator implements Generator {
TypedStructDefinitionNode structDefinition,
Context context
) {
- Function<JavaTypeRef, JavaBlock> decodeBody = structJavaTypeRef -> new JavaBlock(
+ Function<JavaTypeRef, JavaBlock> decodeBody = structJavaTypeRef -> new JavaBlock(
structDefinition.fields().isEmpty()
? List.of(new JavaReturn(
new JavaStaticFieldAccess(structJavaTypeRef, JavaGenerator.INSTANCE_FIELD_NAME)
@@ -827,7 +827,7 @@ public class JavaTransient0Generator implements Generator {
}
private JavaMethodDeclaration generateEncodeMethod(
- Type type,
+ SimpleType type,
JavaBlock body
) {
var javaTypeRef = this.javaGenerator.generateTypeRef(type);
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
index 78f2e91..d6aa888 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java
@@ -31,6 +31,8 @@ public class RustTransient0Generator implements Generator {
private static final RustIdentifier READER_NAME = RustIdentifier.of("reader");
private static final RustIdentifier WRITER_NAME = RustIdentifier.of("writer");
private static final RustIdentifier SHARED_VALUES_NAME = RustIdentifier.of("shared_values");
+ private static final RustIdentifier ENCODE_TYPE_NAME = RustIdentifier.of("Encode");
+ private static final RustIdentifier DECODE_TYPE_NAME = RustIdentifier.of("Decode");
public static OutputConfig parseGeneratorConfig(
Path projectRoot,
@@ -67,7 +69,7 @@ public class RustTransient0Generator implements Generator {
}
private void generateBuiltins() throws IOException {
- var rustModuleName = this.generateTransient0ModuleName(NamespaceName.of());
+ var rustModuleName = builtinsModuleName();
var rustModule = new RustModule(
rustModuleName,
List.of(
@@ -89,12 +91,16 @@ public class RustTransient0Generator implements Generator {
this.rustGenerator.write(rustModule);
}
+ private ArrayList<RustIdentifier> builtinsModuleName() {
+ return this.generateTransient0ModuleName(NamespaceName.of());
+ }
+
private RustItem generateEncodeType() {
var valueType = RustIdentifier.of("T");
var writeType = RustIdentifier.of("TWrite");
return new RustTypeAlias(
Optional.of(RustVisibility.PUB),
- RustIdentifier.of("Encode"),
+ ENCODE_TYPE_NAME,
List.of(
new RustTypeParam(valueType, List.of()),
new RustTypeParam(writeType, List.of(RustTypes.IO_WRITE))
@@ -110,12 +116,18 @@ public class RustTransient0Generator implements Generator {
);
}
+ private RustType encodeType(RustType valueType, RustType writeType) {
+ return RustPath.crate(builtinsModuleName())
+ .addSegment(RustPathSegment.of(ENCODE_TYPE_NAME))
+ .withArgs(List.of(valueType, writeType));
+ }
+
private RustItem generateDecodeType() {
var valueType = RustIdentifier.of("T");
var readType = RustIdentifier.of("TRead");
return new RustTypeAlias(
Optional.of(RustVisibility.PUB),
- RustIdentifier.of("Decode"),
+ DECODE_TYPE_NAME,
List.of(
new RustTypeParam(readType, List.of(RustTypes.IO_READ)),
new RustTypeParam(valueType, List.of())
@@ -130,6 +142,12 @@ public class RustTransient0Generator implements Generator {
);
}
+ private RustType decodeType(RustType readType, RustType valueType) {
+ return RustPath.crate(builtinsModuleName())
+ .addSegment(RustPathSegment.of(DECODE_TYPE_NAME))
+ .withArgs(List.of(readType, valueType));
+ }
+
private RustItem generateEncodeBoolFunction() {
return generateEncodeFunction(
NativeTypes.BOOL,
@@ -442,49 +460,71 @@ public class RustTransient0Generator implements Generator {
}
private RustItem generateEncodeStructFunction(TypedStructDefinitionNode structDefinition) {
- return generateEncodeFunction(
- structDefinition.typeOrThrow(),
- structDefinition.fields().orElse(List.of()).stream()
- .map(field -> generateEncode(
- new RustPrefixExpression(
- RustPrefixOperator.BORROW,
- new RustFieldExpression(
- RustPath.of(VALUE_NAME),
- this.rustGenerator.generateFieldName(field.name())
- )
- ),
- field.type().value()
- ))
- .toList()
- );
+ var fields = structDefinition.fields().orElse(List.of());
+
+ var rustBody = fields.stream()
+ .map(field -> generateEncode(
+ new RustPrefixExpression(
+ RustPrefixOperator.BORROW,
+ new RustFieldExpression(
+ RustPath.of(VALUE_NAME),
+ this.rustGenerator.generateFieldName(field.name())
+ )
+ ),
+ field.type().value()
+ ))
+ .toList();
+
+ return switch (structDefinition.typeOrConstructor()) {
+ case TypeOrConstructor.Constructor<SimpleStructType> constructor ->
+ generateEncodeFunction(
+ constructor.value(),
+ rustBody
+ );
+
+ case TypeOrConstructor.Type<SimpleStructType> type ->
+ generateEncodeFunction(
+ type.value(),
+ rustBody
+ );
+ };
}
private RustItem generateDecodeStructFunction(TypedStructDefinitionNode structDefinition) {
- var rustType = this.rustGenerator.generateRustTypeExpression(structDefinition.typeOrThrow());
-
- return generateDecodeFunction(
- structDefinition.typeOrThrow(),
- structDefinition.fields().isEmpty()
- ? new RustBlockExpression(List.of(), Optional.of(rustType))
- : new RustBlockExpression(
+ Function<RustPath, RustBlockExpression> decodeBody = rustType -> structDefinition.fields().isEmpty()
+ ? new RustBlockExpression(List.of(), Optional.of(rustType))
+ : new RustBlockExpression(
+ structDefinition.fields().get().stream()
+ .<RustStatement>map(field -> new RustLetStatement(
+ this.rustGenerator.generateFieldName(field.name()),
+ false,
+ generateDecode(field.type().value())
+ ))
+ .toList(),
+ Optional.of(new RustStructExpression(
+ rustType,
structDefinition.fields().get().stream()
- .<RustStatement>map(field -> new RustLetStatement(
+ .map(field -> new RustStructExprField(
this.rustGenerator.generateFieldName(field.name()),
- false,
- generateDecode(field.type().value())
+ RustPath.of(this.rustGenerator.generateFieldName(field.name()))
))
- .toList(),
- Optional.of(new RustStructExpression(
- rustType,
- structDefinition.fields().get().stream()
- .map(field -> new RustStructExprField(
- this.rustGenerator.generateFieldName(field.name()),
- RustPath.of(this.rustGenerator.generateFieldName(field.name()))
- ))
- .toList()
- ))
- )
- );
+ .toList()
+ ))
+ );
+
+ return switch (structDefinition.typeOrConstructor()) {
+ case TypeOrConstructor.Constructor<SimpleStructType> constructor ->
+ generateDecodeFunction(
+ constructor.value(),
+ decodeBody
+ );
+
+ case TypeOrConstructor.Type<SimpleStructType> type ->
+ generateDecodeFunction(
+ type.value(),
+ decodeBody.apply(this.rustGenerator.generateRustTypeExpression(type.value()))
+ );
+ };
}
private RustItem generateEncodeSumFunction(
@@ -563,7 +603,7 @@ public class RustTransient0Generator implements Generator {
}
private RustItem generateEncodeFunction(
- Type type,
+ SimpleType type,
List<RustStatement> body
) {
var rustType = this.rustGenerator.generateRustTypeExpression(type);
@@ -572,7 +612,68 @@ public class RustTransient0Generator implements Generator {
Optional.of(RustVisibility.PUB),
encodeMethodName(type),
List.of(),
- generateEncodeParams(rustType),
+ generateEncodeParams(rustType, new RustImplTraitType(RustTypes.IO_WRITE)),
+ Optional.of(
+ RustTypes.ioResult(RustTypes.UNIT)
+ ),
+ Optional.of(new RustBlockExpression(
+ body,
+ Optional.of(
+ new RustCallExpression(
+ RustTypes.IO_RESULT_OK,
+ List.of(new RustTupleExpression(List.of()))
+ )
+ )
+ ))
+ );
+ }
+
+ private RustItem generateEncodeFunction(
+ TypeConstructor<?> constructor,
+ List<RustStatement> body
+ ) {
+ // TODO: need to handle collisions with hobgoblin type params? (similarly for decode)
+ var writeRustTypeParam = new RustTypeParam(
+ RustIdentifier.of("TWrite"),
+ List.of(RustTypes.IO_WRITE)
+ );
+
+ var encodeRustTypeParams = constructor.params().stream()
+ .map(typeParam -> new RustTypeParam(
+ this.rustGenerator.generateTypeName(typeParam.name()),
+ List.of()
+ ))
+ .toList();
+
+ var rustTypeArgs = encodeRustTypeParams.stream()
+ .<RustType>map(rustTypeParam -> RustPath.of(rustTypeParam.name()))
+ .toList();
+
+ var rustType = this.rustGenerator.generateRustTypeExpression(constructor.genericType())
+ .withArgs(rustTypeArgs);
+
+ var typeArgEncodeParams = IntStream.range(0, constructor.params().size())
+ .mapToObj(typeParamIndex -> {
+ var typeParam = constructor.params().get(typeParamIndex);
+ var rustTypeParam = encodeRustTypeParams.get(typeParamIndex);
+ return new RustFunctionParam(
+ generateEncodeVariableName(typeParam),
+ encodeType(RustPath.of(rustTypeParam.name()), RustPath.of(writeRustTypeParam.name()))
+ );
+ })
+ .toList();
+
+ return new RustFunction(
+ Optional.of(RustVisibility.PUB),
+ encodeMethodName(constructor.genericType()),
+ Lists.concat(List.of(
+ List.of(writeRustTypeParam),
+ encodeRustTypeParams
+ )),
+ Lists.concat(List.of(
+ generateEncodeParams(rustType, RustPath.of(writeRustTypeParam.name())),
+ typeArgEncodeParams
+ )),
Optional.of(
RustTypes.ioResult(RustTypes.UNIT)
),
@@ -588,10 +689,10 @@ public class RustTransient0Generator implements Generator {
);
}
- private static List<RustFunctionParam> generateEncodeParams(RustPath rustType) {
+ private static List<RustFunctionParam> generateEncodeParams(RustPath rustType, RustType writeType) {
return List.of(
new RustFunctionParam(VALUE_NAME, new RustSharedReferenceType(rustType)),
- new RustFunctionParam(WRITER_NAME, new RustMutableReferenceType(new RustImplTraitType(RustPath.of("std", "io", "Write")))),
+ new RustFunctionParam(WRITER_NAME, new RustMutableReferenceType(writeType)),
new RustFunctionParam(SHARED_VALUES_NAME, encoderSharedValuesType())
);
}
@@ -602,8 +703,12 @@ public class RustTransient0Generator implements Generator {
);
}
+ private RustIdentifier generateEncodeVariableName(TypeParam typeParam) {
+ return this.rustGenerator.generateFieldName("encode" + typeParam.name());
+ }
+
private RustItem generateDecodeFunction(
- Type type,
+ SimpleType type,
RustBlockExpression body
) {
var rustType = this.rustGenerator.generateRustTypeExpression(type);
@@ -612,7 +717,62 @@ public class RustTransient0Generator implements Generator {
Optional.of(RustVisibility.PUB),
decodeMethodName(type),
List.of(),
- generateDecodeParams(),
+ generateDecodeParams(new RustImplTraitType(RustTypes.IO_READ)),
+ Optional.of(RustTypes.ioResult(rustType)),
+ Optional.of(new RustBlockExpression(
+ body.statements(),
+ body.finalOperand().map(finalOperand -> new RustCallExpression(RustTypes.IO_RESULT_OK, List.of(finalOperand)))
+ ))
+ );
+ }
+
+ private RustItem generateDecodeFunction(
+ TypeConstructor<?> constructor,
+ Function<RustPath, RustBlockExpression> generateBody
+ ) {
+ var readTypeParam = new RustTypeParam(
+ RustIdentifier.of("TRead"),
+ List.of(RustTypes.IO_READ)
+ );
+
+ var decodeRustTypeParams = constructor.params().stream()
+ .map(typeParam -> new RustTypeParam(
+ this.rustGenerator.generateTypeName(typeParam.name()),
+ List.of()
+ ))
+ .toList();
+
+ var rustTypeArgs = decodeRustTypeParams.stream()
+ .<RustType>map(rustTypeParam -> RustPath.of(rustTypeParam.name()))
+ .toList();
+
+ var rustType = this.rustGenerator.generateRustTypeExpression(constructor.genericType())
+ .withArgs(rustTypeArgs);
+
+ var typeArgDecoderParams = IntStream.range(0, constructor.params().size())
+ .mapToObj(typeParamIndex -> {
+ var typeParam = constructor.params().get(typeParamIndex);
+ var rustTypeParam = decodeRustTypeParams.get(typeParamIndex);
+ return new RustFunctionParam(
+ generateDecodeVariableName(typeParam),
+ decodeType(RustPath.of(readTypeParam.name()), RustPath.of(rustTypeParam.name()))
+ );
+ })
+ .toList();
+
+ var body = generateBody.apply(rustType);
+
+ return new RustFunction(
+ Optional.of(RustVisibility.PUB),
+ decodeMethodName(constructor.genericType()),
+ Lists.concat(List.of(
+ List.of(readTypeParam),
+ decodeRustTypeParams
+ )),
+ Lists.concat(List.of(
+ generateDecodeParams(RustPath.of(readTypeParam.name())),
+ typeArgDecoderParams
+ )),
Optional.of(RustTypes.ioResult(rustType)),
Optional.of(new RustBlockExpression(
body.statements(),
@@ -621,9 +781,9 @@ public class RustTransient0Generator implements Generator {
);
}
- private static List<RustFunctionParam> generateDecodeParams() {
+ private static List<RustFunctionParam> generateDecodeParams(RustType readType) {
return List.of(
- new RustFunctionParam(READER_NAME, new RustMutableReferenceType(new RustImplTraitType(RustPath.of("std", "io", "Read")))),
+ new RustFunctionParam(READER_NAME, new RustMutableReferenceType(readType)),
new RustFunctionParam(SHARED_VALUES_NAME, decoderSharedValuesType())
);
}
@@ -634,6 +794,10 @@ public class RustTransient0Generator implements Generator {
);
}
+ private RustIdentifier generateDecodeVariableName(TypeParam typeParam) {
+ return this.rustGenerator.generateFieldName("decode" + typeParam.name());
+ }
+
private RustStatement generateEncode(RustExpression value, Type type) {
return switch (type) {
case ConstructedType constructedType -> {
@@ -653,7 +817,8 @@ public class RustTransient0Generator implements Generator {
constructedType.args().stream()
.<RustExpression>map(typeArg -> new RustClosureExpression(
RustGenerator.functionParamsToClosureParams(generateEncodeParams(
- this.rustGenerator.generateRustTypeExpression(typeArg)
+ this.rustGenerator.generateRustTypeExpression(typeArg),
+ new RustImplTraitType(RustTypes.IO_WRITE)
)),
new RustBlockExpression(
List.of(generateEncode(RustPath.of(VALUE_NAME), typeArg)),
@@ -676,8 +841,11 @@ public class RustTransient0Generator implements Generator {
yield new RustExpressionStatement(generateTodo());
}
- case TypeParam _ -> {
- yield new RustExpressionStatement(generateTodo());
+ case TypeParam typeParam -> {
+ yield new RustExpressionStatement(new RustTryPropagationExpression(new RustCallExpression(
+ RustPath.of(generateEncodeVariableName(typeParam)),
+ List.of(value, RustPath.of(WRITER_NAME), RustPath.of(SHARED_VALUES_NAME))
+ )));
}
};
}
@@ -699,7 +867,9 @@ public class RustTransient0Generator implements Generator {
constructedType,
constructedType.args().stream()
.<RustExpression>map(typeArg -> new RustClosureExpression(
- RustGenerator.functionParamsToClosureParams(generateDecodeParams()),
+ RustGenerator.functionParamsToClosureParams(
+ generateDecodeParams(new RustImplTraitType(RustTypes.IO_READ))
+ ),
new RustCallExpression(
RustTypes.IO_RESULT_OK,
List.of(generateDecode(typeArg))
@@ -719,8 +889,11 @@ public class RustTransient0Generator implements Generator {
yield generateTodo();
}
- case TypeParam _ -> {
- yield generateTodo();
+ case TypeParam typeParam -> {
+ yield new RustTryPropagationExpression(new RustCallExpression(
+ RustPath.of(generateDecodeVariableName(typeParam)),
+ List.of(RustPath.of(READER_NAME), RustPath.of(SHARED_VALUES_NAME))
+ ));
}
};
}