diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-08-31 23:07:49 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-08-31 23:07:49 +0100 |
| commit | 9a2c148579957a6c68a8152daf5531f8194e3e31 (patch) | |
| tree | 65b322e4bd6f840bf2db0c472d3ef6b7b5df9eca /src/main/java | |
| parent | 9ae0aa5e9fe3ae8e52c48fc1ad23ee047752ff89 (diff) | |
Support sum types in typescript-types
Diffstat (limited to 'src/main/java')
2 files changed, 71 insertions, 8 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/typescripttypes/TypescriptTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/typescripttypes/TypescriptTypesGenerator.java index 9a21ea9..ac9cbb9 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/typescripttypes/TypescriptTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/typescripttypes/TypescriptTypesGenerator.java @@ -6,6 +6,7 @@ import org.zwobble.hobgoblin.compiler.output.generators.Generator; import org.zwobble.hobgoblin.compiler.output.generators.GeneratorDefinition; import org.zwobble.hobgoblin.compiler.output.generators.typescript.TypescriptGenerator; import org.zwobble.hobgoblin.compiler.output.generators.typescript.TypescriptGeneratorConfig; +import org.zwobble.hobgoblin.compiler.output.lang.typescript.TypescriptTypes; import org.zwobble.hobgoblin.compiler.output.lang.typescript.ast.*; import org.zwobble.hobgoblin.compiler.typechecker.TypesInfo; import org.zwobble.hobgoblin.compiler.types.SimpleStructType; @@ -41,6 +42,8 @@ public class TypescriptTypesGenerator implements Generator { } }; + private static final TypescriptIdentifier TAG_PROPERTY_NAME = TypescriptIdentifier.of("$tag"); + private static OutputConfig parseGeneratorConfig( Path projectRoot, Json5ObjectReader generatorJson, @@ -67,25 +70,31 @@ public class TypescriptTypesGenerator implements Generator { @Override public void generate(List<TypedNamespaceNode> namespaces, TypesInfo typesInfo) throws IOException { for (var namespace : namespaces) { - var typescriptModule = generateNamespace(namespace); + var typescriptModule = generateNamespace(namespace, typesInfo); this.typescriptGenerator.write(typescriptModule); } } - private TypescriptModule generateNamespace(TypedNamespaceNode namespace) { + private TypescriptModule generateNamespace( + TypedNamespaceNode namespace, + TypesInfo typesInfo + ) { var typescriptModuleName = namespace.namespaceName().parts().stream() .map(part -> this.typescriptGenerator.generateModuleName(part)) .toList(); var statements = namespace.body().stream() - .flatMap(statement -> generateNamespaceStatement(statement).stream()) + .flatMap(statement -> generateNamespaceStatement(statement, typesInfo).stream()) .toList(); return new TypescriptModule(typescriptModuleName, statements); } - private List<TypescriptStatement> generateNamespaceStatement(TypedNamespaceStatementNode statement) { + private List<TypescriptStatement> generateNamespaceStatement( + TypedNamespaceStatementNode statement, + TypesInfo typesInfo + ) { switch (statement) { case TypedEnumDefinitionNode _ -> { throw new UnsupportedOperationException("TODO"); @@ -96,16 +105,19 @@ public class TypescriptTypesGenerator implements Generator { } case TypedStructDefinitionNode structDefinition -> { - return generateStructDefinition(structDefinition); + return generateStructDefinition(structDefinition, typesInfo); } - case TypedSumDefinitionNode _ -> { - throw new UnsupportedOperationException("TODO"); + case TypedSumDefinitionNode sumDefinition -> { + return generateSumDefinition(sumDefinition, typesInfo); } } } - private List<TypescriptStatement> generateStructDefinition(TypedStructDefinitionNode structDefinition) { + private List<TypescriptStatement> generateStructDefinition( + TypedStructDefinitionNode structDefinition, + TypesInfo typesInfo + ) { var typescriptTypeName = this.typescriptGenerator.generateTypeName(structDefinition.name()); var typescriptTypeParams = switch (structDefinition.typeOrConstructor()) { @@ -122,6 +134,36 @@ public class TypescriptTypesGenerator implements Generator { var body = new ArrayList<TypescriptClassElement>(); + if (!typesInfo.variantOf(structDefinition.typeOrConstructor().unboundType()).isEmpty()) { + body.add(new TypescriptClassFieldDeclaration( + TAG_PROPERTY_NAME, + TypescriptVisibility.PUBLIC, + true, + true, + Optional.empty(), + Optional.of(new TypescriptCall( + TypescriptTypes.SYMBOL, + // TODO: add type name as string + List.of() + )) + )); + + body.add(new TypescriptClassFieldDeclaration( + TAG_PROPERTY_NAME, + TypescriptVisibility.PUBLIC, + false, + true, + Optional.of(new TypescriptTypeof(new TypescriptFieldAccess( + new TypescriptRef(typescriptTypeName), + TAG_PROPERTY_NAME + ))), + Optional.of(new TypescriptFieldAccess( + new TypescriptRef(typescriptTypeName), + TAG_PROPERTY_NAME + )) + )); + } + for (var field : structDefinition.fields().orElse(List.of())) { body.add(new TypescriptClassFieldDeclaration( this.typescriptGenerator.generateFieldName(field.name()), @@ -181,4 +223,24 @@ public class TypescriptTypesGenerator implements Generator { new TypescriptExportNamesStatement(List.of(typescriptTypeName)) ); } + + private List<TypescriptStatement> generateSumDefinition( + TypedSumDefinitionNode sumDefinition, + TypesInfo typesInfo + ) { + var typescriptTypeName = this.typescriptGenerator.generateTypeName(sumDefinition.name()); + + return List.of( + new TypescriptTypeAlias( + typescriptTypeName, + new TypescriptTypeUnion( + sumDefinition.variants().stream() + .map(variant -> this.typescriptGenerator.generateTypeExpression(variant.type().value())) + .toList() + ) + ), + // TODO: represent type exports properly in AST + new TypescriptExportNamesStatement(List.of(TypescriptIdentifier.of("type " + typescriptTypeName.value()))) + ); + } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/typescript/TypescriptTypes.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/typescript/TypescriptTypes.java index 1403187..22f24a3 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/typescript/TypescriptTypes.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/typescript/TypescriptTypes.java @@ -9,4 +9,5 @@ public class TypescriptTypes { public static final TypescriptRef NUMBER = new TypescriptRef(TypescriptIdentifier.of("number")); public static final TypescriptRef READONLY_ARRAY = new TypescriptRef(TypescriptIdentifier.of("ReadonlyArray")); + public static final TypescriptRef SYMBOL = new TypescriptRef(TypescriptIdentifier.of("Symbol")); } |
