From d0c6cc5511f5b953ca1a4184e6c7b903e4bb7450 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 30 Jun 2026 21:23:51 +0100 Subject: Fully qualify Rust type expressions --- .../generators/rusttypes/RustTypesGenerator.java | 66 ++++++++++++++++++---- .../output/lang/rust/ast/RustTypePathSegment.java | 4 ++ 2 files changed, 58 insertions(+), 12 deletions(-) (limited to 'src/main') 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 776e401..c4af4e7 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 @@ -14,6 +14,7 @@ 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.stream.Collectors; @@ -39,7 +40,8 @@ public class RustTypesGenerator implements Generator { @Override public void generate(List namespaces, TypesInfo typesInfo) throws IOException { for (var namespace : namespaces) { - var rustModule = generateNamespace(namespace); + var context = new Context(namespace.namespaceName()); + var rustModule = generateNamespace(namespace, context); write(rustModule); } @@ -56,11 +58,11 @@ public class RustTypesGenerator implements Generator { } } - private RustModule generateNamespace(TypedNamespaceNode namespace) { + private RustModule generateNamespace(TypedNamespaceNode namespace, Context context) { var rustModuleName = generateNamespaceName(namespace.namespaceName()); var rustItems = namespace.body().stream() - .flatMap(statement -> generateNamespaceStatement(statement).stream()) + .flatMap(statement -> generateNamespaceStatement(statement, context).stream()) .toList(); return new RustModule(rustModuleName, rustItems); @@ -72,7 +74,10 @@ public class RustTypesGenerator implements Generator { .toList(); } - private List generateNamespaceStatement(TypedNamespaceStatementNode statement) { + private List generateNamespaceStatement( + TypedNamespaceStatementNode statement, + Context context + ) { return switch (statement) { case TypedEnumDefinitionNode enumDefinition -> { yield List.of(); @@ -86,7 +91,10 @@ public class RustTypesGenerator implements Generator { var rustStructName = generateTypeName(structDefinition.name()); var rustFields = structDefinition.fields().stream() - .map(field -> new RustStructField(generateFieldName(field.name()), generateRustTypeExpression(field.type()))) + .map(field -> new RustStructField( + generateFieldName(field.name()), + generateRustTypeExpression(field.type(), context) + )) .toList(); var rustStruct = new RustStructStruct(rustStructName, rustFields, structDefinition.docComment()); @@ -100,17 +108,23 @@ public class RustTypesGenerator implements Generator { }; } - private RustType generateRustTypeExpression(TypedTypeLevelExpressionNode type) { - return generateRustTypeExpression(type.value()); + private RustType generateRustTypeExpression( + TypedTypeLevelExpressionNode type, + Context context + ) { + return generateRustTypeExpression(type.value(), context); } - private RustType generateRustTypeExpression(Type type) { + private RustType generateRustTypeExpression(Type type, Context context) { return switch (type) { case ConstructedNativeType constructedNativeType -> { // TODO: avoid cast - var rustType = (RustTypePath) generateRustTypeExpression(constructedNativeType.constructor().genericType()); + var rustType = (RustTypePath) generateRustTypeExpression( + constructedNativeType.constructor().genericType(), + context + ); var rustArgs = constructedNativeType.args().stream() - .map(arg -> generateRustTypeExpression(arg)) + .map(arg -> generateRustTypeExpression(arg, context)) .toList(); yield rustType.withArgs(rustArgs); } @@ -126,8 +140,11 @@ public class RustTypesGenerator implements Generator { } case StructType structType -> { - // TODO: qualify name - yield RustTypePath.of(generateTypeName(structType.name())); + yield generateTypePath( + structType.namespaceName(), + structType.name(), + context + ); } case SumType sumType -> { @@ -144,6 +161,23 @@ public class RustTypesGenerator implements Generator { }; } + private RustType generateTypePath(NamespaceName namespaceName, String typeName, Context context) { + var segments = new ArrayList(); + // TODO: use crate as a keyword, not an identifier + segments.add(RustTypePathSegment.of(new RustIdentifier("crate"))); + for (var moduleName : this.namespaceNameToRustCrateModulePath(namespaceName)) { + segments.add(RustTypePathSegment.of(moduleName)); + } + segments.add(RustTypePathSegment.of(generateTypeName(typeName))); + return new RustTypePath(segments); + } + + private List namespaceNameToRustCrateModulePath(NamespaceName namespaceName) { + return namespaceName.parts().stream() + .map(part -> generateModuleName(part)) + .toList(); + } + private RustIdentifier generateFieldName(String fieldName) { return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(fieldName)); } @@ -155,4 +189,12 @@ public class RustTypesGenerator implements Generator { private RustIdentifier generateModuleName(String part) { return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(part)); } + + private static class Context { + private final NamespaceName currentNamespaceName; + + private Context(NamespaceName currentNamespaceName) { + this.currentNamespaceName = currentNamespaceName; + } + } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java index 4473aa3..78348c5 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java @@ -35,6 +35,10 @@ public record RustTypePathSegment(org.zwobble.hobgoblin.compiler.output.lang.rus } // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment body + public static RustTypePathSegment of(RustIdentifier name) { + return new RustTypePathSegment(new RustPathIdentSegmentIdentifier(name), Optional.empty()); + } + public RustTypePathSegment withArgs(List args) { if (this.args.isPresent()) { throw new IllegalArgumentException("Type path segment already has args"); -- cgit v1.2.3