summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-08-31 23:07:49 +0100
committerMichael Williamson <mike@zwobble.org>2026-08-31 23:07:49 +0100
commit9a2c148579957a6c68a8152daf5531f8194e3e31 (patch)
tree65b322e4bd6f840bf2db0c472d3ef6b7b5df9eca /src/main/java
parent9ae0aa5e9fe3ae8e52c48fc1ad23ee047752ff89 (diff)
Support sum types in typescript-types
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/typescripttypes/TypescriptTypesGenerator.java78
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/typescript/TypescriptTypes.java1
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"));
}