diff options
Diffstat (limited to 'src/main')
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)) + )); } }; } |
