diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-07-14 19:12:35 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-07-14 19:12:35 +0100 |
| commit | 9a6b9d2f707eed6cafd9d2aa8dd6a079190fce11 (patch) | |
| tree | 4312e2d7c942d79ff9315345630fb5be27f6e9e4 /src | |
| parent | f8cbdc16c4bdb4ee82a34cba92e1168700d3e005 (diff) | |
Extract RustGenerator
Diffstat (limited to 'src')
2 files changed, 144 insertions, 125 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java new file mode 100644 index 0000000..c421ca4 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java @@ -0,0 +1,124 @@ +package org.zwobble.hobgoblin.compiler.output.generators.rust; + +import org.zwobble.hobgoblin.compiler.output.lang.rust.RustWriter; +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*; +import org.zwobble.hobgoblin.compiler.types.*; +import org.zwobble.hobgoblin.compiler.util.Casing; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class RustGenerator { + private final Path outputPath; + private final RustGeneratorConfig config; + + public RustGenerator(Path outputPath, RustGeneratorConfig config) { + this.outputPath = outputPath; + this.config = config; + } + + public void write(RustModule rustModule) throws IOException { + var path = this.outputPath.resolve( + rustModule.name().stream() + .map(name -> name.value()) + .collect(Collectors.joining(File.separator)) + ".rs" + ); + try (var writer = RustWriter.file(path)) { + writer.writeModule(rustModule); + } + } + + public RustType generateRustTypeExpression(Type type) { + return switch (type) { + case ConstructedNativeType constructedNativeType -> { + // TODO: avoid cast + var rustType = (RustTypePath) generateRustTypeExpression( + constructedNativeType.constructor().genericType() + ); + var rustArgs = constructedNativeType.args().stream() + .map(arg -> generateRustTypeExpression(arg)) + .toList(); + yield rustType.withArgs(rustArgs); + } + + case EnumType enumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case SimpleNativeType simpleNativeType -> { + yield this.config.nativeTypeConfig(simpleNativeType) + .map(config -> config.type()) + .orElseGet(() -> generateTypePath( + simpleNativeType.namespaceName(), + simpleNativeType.name() + )); + } + + case StructType structType -> { + yield generateTypePath( + structType.namespaceName(), + structType.name() + ); + } + + case SumType sumType -> { + yield generateTypePath( + sumType.namespaceName(), + sumType.name() + ); + } + + case TypeLevelValueType typeLevelValueType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeParam typeParam -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + + private RustType generateTypePath(NamespaceName namespaceName, String typeName) { + var segments = new ArrayList<RustTypePathSegment>(); + segments.add(RustTypePathSegment.crate()); + for (var moduleName : this.namespaceNameToRustCrateModulePath(namespaceName)) { + segments.add(RustTypePathSegment.of(moduleName)); + } + segments.add(RustTypePathSegment.of(generateTypeName(typeName))); + return new RustTypePath(segments); + } + + private List<RustIdentifier> namespaceNameToRustCrateModulePath(NamespaceName namespaceName) { + return namespaceName.parts().stream() + .map(part -> generateModuleName(part)) + .toList(); + } + + public RustIdentifier generateFieldName(String fieldName) { + return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(fieldName)); + } + + public RustIdentifier generateTypeName(String typeName) { + return new RustIdentifier(typeName); + } + + public RustIdentifier generateModuleName(String part) { + return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(part)); + } + + public RustIdentifier generateVariantName(String enumVariantName) { + return generateTypeName(Casing.lowerCamelCaseToUpperCamelCase(enumVariantName)); + } + + public RustIdentifier generateVariantName(Type type) { + if (type instanceof StructType structType) { + return generateTypeName(structType.name()); + } else { + throw new UnsupportedOperationException("TODO"); + } + } +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java index 66a19fe..d1248b4 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java @@ -3,21 +3,19 @@ package org.zwobble.hobgoblin.compiler.output.generators.rusttypes; import org.zwobble.hobgoblin.compiler.ast.typed.*; import org.zwobble.hobgoblin.compiler.config.OutputConfig; import org.zwobble.hobgoblin.compiler.output.generators.Generator; +import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGenerator; import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGeneratorConfig; -import org.zwobble.hobgoblin.compiler.output.lang.rust.RustWriter; import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*; import org.zwobble.hobgoblin.compiler.typechecker.TypesInfo; -import org.zwobble.hobgoblin.compiler.types.*; -import org.zwobble.hobgoblin.compiler.util.Casing; +import org.zwobble.hobgoblin.compiler.types.NamespaceName; +import org.zwobble.hobgoblin.compiler.types.Type; import org.zwobble.json5.reader.Json5ObjectReader; -import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; public class RustTypesGenerator implements Generator { public static final String NAME = "rust-types"; @@ -33,15 +31,17 @@ public class RustTypesGenerator implements Generator { var rustConfig = RustGeneratorConfig.parseLangsConfig(langsJson); - return new RustTypesGenerator(outputPath, rustConfig); + var rustGenerator = new RustGenerator(outputPath, rustConfig); + + return new RustTypesGenerator(rustGenerator, rustConfig); }; } - private final Path outputPath; + private final RustGenerator rustGenerator; private final RustGeneratorConfig config; - private RustTypesGenerator(Path outputPath, RustGeneratorConfig config) { - this.outputPath = outputPath; + private RustTypesGenerator(RustGenerator rustGenerator, RustGeneratorConfig config) { + this.rustGenerator = rustGenerator; this.config = config; } @@ -51,18 +51,7 @@ public class RustTypesGenerator implements Generator { var context = new Context(namespace.namespaceName()); var rustModule = generateNamespace(namespace, context); - write(rustModule); - } - } - - private void write(RustModule rustModule) throws IOException { - var path = this.outputPath.resolve( - rustModule.name().stream() - .map(name -> name.value()) - .collect(Collectors.joining(File.separator)) + ".rs" - ); - try (var writer = RustWriter.file(path)) { - writer.writeModule(rustModule); + this.rustGenerator.write(rustModule); } } @@ -78,7 +67,7 @@ public class RustTypesGenerator implements Generator { private List<RustIdentifier> generateNamespaceName(NamespaceName namespaceName) { return namespaceName.parts().stream() - .map(part -> generateModuleName(part)) + .map(part -> this.rustGenerator.generateModuleName(part)) .toList(); } @@ -109,11 +98,11 @@ public class RustTypesGenerator implements Generator { TypedEnumDefinitionNode enumDefinition, Context context ) { - var rustEnumName = generateTypeName(enumDefinition.name()); + var rustEnumName = this.rustGenerator.generateTypeName(enumDefinition.name()); var rustVariants = enumDefinition.variants().stream() .map(variant -> new RustEnumVariant( - generateVariantName(variant.name()), + this.rustGenerator.generateVariantName(variant.name()), new RustEnumVariantNoFields() )) .toList(); @@ -131,11 +120,11 @@ public class RustTypesGenerator implements Generator { TypedStructDefinitionNode structDefinition, Context context ) { - var rustStructName = generateTypeName(structDefinition.name()); + var rustStructName = this.rustGenerator.generateTypeName(structDefinition.name()); var rustFields = structDefinition.fields().stream() .map(field -> new RustStructField( - generateFieldName(field.name()), + this.rustGenerator.generateFieldName(field.name()), generateRustTypeExpression(field.type(), context) )) .toList(); @@ -151,7 +140,7 @@ public class RustTypesGenerator implements Generator { ) { var items = new ArrayList<RustItem>(); - var rustEnumName = generateTypeName(sumDefinition.name()); + var rustEnumName = this.rustGenerator.generateTypeName(sumDefinition.name()); var rustVariants = sumDefinition.variants().stream() .map(variant -> { @@ -163,7 +152,7 @@ public class RustTypesGenerator implements Generator { } return new RustEnumVariant( - generateVariantName(variant.type().value()), + this.rustGenerator.generateVariantName(variant.type().value()), new RustEnumVariantTuple(List.of( new RustTupleField(variantType) )) @@ -176,7 +165,7 @@ public class RustTypesGenerator implements Generator { for (var variant : sumDefinition.variants()) { var variantType = generateRustTypeExpression(variant.type(), context); - var variantName = generateVariantName(variant.type().value()); + var variantName = this.rustGenerator.generateVariantName(variant.type().value()); var innerValueName = new RustIdentifier("value"); RustExpression innerValue = new RustPathInExpression(List.of( new RustPathExprSegment( @@ -195,7 +184,7 @@ public class RustTypesGenerator implements Generator { var fromImpl = new RustTraitImpl( RustTypePath.global("std", "convert", "From") .withArgs(List.of(variantType)), - generateRustTypeExpression(sumDefinition.type(), context), + this.rustGenerator.generateRustTypeExpression(sumDefinition.type()), List.of( new RustFunction( new RustIdentifier("from"), @@ -223,101 +212,7 @@ public class RustTypesGenerator implements Generator { TypedTypeLevelExpressionNode<Type> type, Context context ) { - return generateRustTypeExpression(type.value(), context); - } - - private RustType generateRustTypeExpression(Type type, Context context) { - return switch (type) { - case ConstructedNativeType constructedNativeType -> { - // TODO: avoid cast - var rustType = (RustTypePath) generateRustTypeExpression( - constructedNativeType.constructor().genericType(), - context - ); - var rustArgs = constructedNativeType.args().stream() - .map(arg -> generateRustTypeExpression(arg, context)) - .toList(); - yield rustType.withArgs(rustArgs); - } - - case EnumType enumType -> { - throw new UnsupportedOperationException("TODO"); - } - - case SimpleNativeType simpleNativeType -> { - yield this.config.nativeTypeConfig(simpleNativeType) - .map(config -> config.type()) - .orElseGet(() -> generateTypePath( - simpleNativeType.namespaceName(), - simpleNativeType.name(), - context - )); - } - - case StructType structType -> { - yield generateTypePath( - structType.namespaceName(), - structType.name(), - context - ); - } - - case SumType sumType -> { - yield generateTypePath( - sumType.namespaceName(), - sumType.name(), - context - ); - } - - case TypeLevelValueType typeLevelValueType -> { - throw new UnsupportedOperationException("TODO"); - } - - case TypeParam typeParam -> { - throw new UnsupportedOperationException("TODO"); - } - }; - } - - private RustType generateTypePath(NamespaceName namespaceName, String typeName, Context context) { - var segments = new ArrayList<RustTypePathSegment>(); - segments.add(RustTypePathSegment.crate()); - for (var moduleName : this.namespaceNameToRustCrateModulePath(namespaceName)) { - segments.add(RustTypePathSegment.of(moduleName)); - } - segments.add(RustTypePathSegment.of(generateTypeName(typeName))); - return new RustTypePath(segments); - } - - private List<RustIdentifier> namespaceNameToRustCrateModulePath(NamespaceName namespaceName) { - return namespaceName.parts().stream() - .map(part -> generateModuleName(part)) - .toList(); - } - - private RustIdentifier generateFieldName(String fieldName) { - return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(fieldName)); - } - - private RustIdentifier generateTypeName(String typeName) { - return new RustIdentifier(typeName); - } - - private RustIdentifier generateModuleName(String part) { - return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(part)); - } - - private RustIdentifier generateVariantName(String enumVariantName) { - return generateTypeName(Casing.lowerCamelCaseToUpperCamelCase(enumVariantName)); - } - - private RustIdentifier generateVariantName(Type type) { - if (type instanceof StructType structType) { - return generateTypeName(structType.name()); - } else { - throw new UnsupportedOperationException("TODO"); - } + return this.rustGenerator.generateRustTypeExpression(type.value()); } private static class Context { |
