From cd5745dfdf422ceb2a4154b575a8c512b41a8f66 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 2 May 2026 10:04:44 +0100 Subject: Create generators from config --- examples/01-struct/hobgoblin.json5 | 10 +++- examples/02-sum/hobgoblin.json5 | 10 +++- pom.xml | 5 ++ .../hobgoblin/compiler/HobgoblinCompiler.java | 8 ++- .../hobgoblin/compiler/config/OutputConfig.java | 7 +++ .../hobgoblin/compiler/config/ProjectConfig.java | 68 ++++++++++++++++++++++ .../generators/javatypes/JavaTypesGenerator.java | 14 +++++ .../zwobble/hobgoblin/compiler/ExampleTests.java | 8 +-- 8 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/config/OutputConfig.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/config/ProjectConfig.java diff --git a/examples/01-struct/hobgoblin.json5 b/examples/01-struct/hobgoblin.json5 index 0967ef4..b6bb102 100644 --- a/examples/01-struct/hobgoblin.json5 +++ b/examples/01-struct/hobgoblin.json5 @@ -1 +1,9 @@ -{} +{ + "outputs": [ + { + "generator": "java-types", + "path": "output/java/src/gen/java", + "package-name": "org.zwobble.example.types" + }, + ], +} diff --git a/examples/02-sum/hobgoblin.json5 b/examples/02-sum/hobgoblin.json5 index 0967ef4..b6bb102 100644 --- a/examples/02-sum/hobgoblin.json5 +++ b/examples/02-sum/hobgoblin.json5 @@ -1 +1,9 @@ -{} +{ + "outputs": [ + { + "generator": "java-types", + "path": "output/java/src/gen/java", + "package-name": "org.zwobble.example.types" + }, + ], +} diff --git a/pom.xml b/pom.xml index 7c2a6bf..fc4c716 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,11 @@ source-text 0.1.0 + + org.zwobble.json5 + zwobble-json5 + 0.1.0 + org.junit.jupiter junit-jupiter diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java b/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java index 698d68f..873ecfd 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/HobgoblinCompiler.java @@ -2,7 +2,7 @@ package org.zwobble.hobgoblin.compiler; import org.zwobble.hobgoblin.compiler.ast.typed.TypedNamespaceNode; import org.zwobble.hobgoblin.compiler.builtins.BuiltinTypes; -import org.zwobble.hobgoblin.compiler.output.generators.Generator; +import org.zwobble.hobgoblin.compiler.config.ProjectConfig; import org.zwobble.hobgoblin.compiler.parser.Parser; import org.zwobble.hobgoblin.compiler.typechecker.TypeChecker; import org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerGlobalContext; @@ -14,7 +14,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.List; public class HobgoblinCompiler { public static final String FILE_NAME_EXTENSION = ".hob"; @@ -22,7 +21,10 @@ public class HobgoblinCompiler { private HobgoblinCompiler() { } - public static void compile(Path projectRoot, List generators) throws IOException { + public static void compile(Path projectRoot) throws IOException { + var config = ProjectConfig.read(projectRoot); + var generators = config.createGenerators(); + var sourceDirectory = projectRoot.resolve("src"); var sourceFiles = sourceDirectory.toFile() .listFiles(file -> file.toPath().toString().endsWith(FILE_NAME_EXTENSION)); diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/config/OutputConfig.java b/src/main/java/org/zwobble/hobgoblin/compiler/config/OutputConfig.java new file mode 100644 index 0000000..ae31bdd --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/config/OutputConfig.java @@ -0,0 +1,7 @@ +package org.zwobble.hobgoblin.compiler.config; + +import org.zwobble.hobgoblin.compiler.output.generators.Generator; + +public interface OutputConfig { + Generator createGenerator(); +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/config/ProjectConfig.java b/src/main/java/org/zwobble/hobgoblin/compiler/config/ProjectConfig.java new file mode 100644 index 0000000..ee70dba --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/config/ProjectConfig.java @@ -0,0 +1,68 @@ +package org.zwobble.hobgoblin.compiler.config; + +import org.zwobble.hobgoblin.compiler.output.generators.Generator; +import org.zwobble.hobgoblin.compiler.output.generators.javatypes.JavaTypesGenerator; +import org.zwobble.json5.parser.Json5Parser; +import org.zwobble.json5.values.Json5Array; +import org.zwobble.json5.values.Json5Object; +import org.zwobble.json5.values.Json5String; +import org.zwobble.json5.values.Json5Value; +import org.zwobble.sourcetext.SourceText; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public record ProjectConfig( + List output +) { + public static ProjectConfig read(Path projectRoot) throws IOException { + var configPath = projectRoot.resolve("hobgoblin.json5"); + var contents = Files.readString(configPath); + var sourceText = SourceText.fromString(configPath.toString(), contents); + return fromSourceText(projectRoot, sourceText); + } + + private static ProjectConfig fromSourceText(Path projectRoot, SourceText sourceText) { + return fromJson5(projectRoot, Json5Parser.parse(sourceText)); + } + + private static ProjectConfig fromJson5(Path projectRoot, Json5Value document) { + if (!(document instanceof Json5Object documentObject)) { + throw new UnsupportedOperationException("TODO"); + } + + var outputsValue = documentObject.getValue("outputs").orElseThrow(); + if (!(outputsValue instanceof Json5Array outputsArray)) { + throw new UnsupportedOperationException("TODO"); + } + + var outputs = new ArrayList(); + for (var outputValue : outputsArray.elements()) { + if (!(outputValue instanceof Json5Object outputObject)) { + throw new UnsupportedOperationException("TODO"); + } + var generatorName = (Json5String) outputObject.getValue("generator").orElseThrow(); + + var output = switch (generatorName.value()) { + case JavaTypesGenerator.NAME -> + JavaTypesGenerator.parseOutputConfig(projectRoot, outputObject); + + default -> + throw new UnsupportedOperationException("TODO"); + }; + + outputs.add(output); + } + + return new ProjectConfig(outputs); + } + + public List createGenerators() { + return this.output.stream() + .map(output -> output.createGenerator()) + .toList(); + } +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java index 98d4c12..4c06e8e 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java @@ -5,11 +5,14 @@ import org.zwobble.hobgoblin.compiler.ast.typed.TypedStructDefinitionNode; import org.zwobble.hobgoblin.compiler.ast.typed.TypedSumDefinitionNode; import org.zwobble.hobgoblin.compiler.ast.typed.TypedTypeLevelExpressionNode; import org.zwobble.hobgoblin.compiler.builtins.BuiltinTypes; +import org.zwobble.hobgoblin.compiler.config.OutputConfig; import org.zwobble.hobgoblin.compiler.output.CodeWriter; import org.zwobble.hobgoblin.compiler.output.generators.Generator; import org.zwobble.hobgoblin.compiler.output.java.JavaWriter; import org.zwobble.hobgoblin.compiler.output.java.ast.*; import org.zwobble.hobgoblin.compiler.types.*; +import org.zwobble.json5.values.Json5Object; +import org.zwobble.json5.values.Json5String; import java.io.File; import java.io.IOException; @@ -19,6 +22,17 @@ import java.util.HashMap; import java.util.List; public class JavaTypesGenerator implements Generator { + public static final String NAME = "java-types"; + + public static OutputConfig parseOutputConfig(Path projectRoot, Json5Object output) { + return () -> { + var relativeOutputPath = ((Json5String) output.getValue("path").orElseThrow()).value(); + var outputPath = projectRoot.resolve(relativeOutputPath); + var packageName = ((Json5String) output.getValue("package-name").orElseThrow()).value(); + return new JavaTypesGenerator(outputPath, packageName); + }; + } + private final Path sourceRootDirectory; private final List packageName; diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/ExampleTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/ExampleTests.java index fb5cc55..fd38a84 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/ExampleTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/ExampleTests.java @@ -2,7 +2,6 @@ package org.zwobble.hobgoblin.compiler; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; -import org.zwobble.hobgoblin.compiler.output.generators.javatypes.JavaTypesGenerator; import org.zwobble.hobgoblin.compiler.testing.TestProcessRunner; import java.io.IOException; @@ -22,12 +21,7 @@ public class ExampleTests { private void runTest(ExampleSet exampleSet) throws IOException, InterruptedException { var javaProjectPath = exampleSet.path().resolve("output/java"); - var javaTypesGenerator = new JavaTypesGenerator( - javaProjectPath.resolve("src/gen/java"), - "org.zwobble.example.types" - ); - var generators = List.of(javaTypesGenerator); - HobgoblinCompiler.compile(exampleSet.path(), generators); + HobgoblinCompiler.compile(exampleSet.path()); TestProcessRunner.command(List.of("mvn", "compile")) .cwd(javaProjectPath) -- cgit v1.2.3