From 0720cb87b0e15fb015f7d24b2076f158e7da4034 Mon Sep 17 00:00:00 2001 From: Colin Date: Sun, 21 Mar 2021 19:17:01 -0400 Subject: [PATCH] Added machine and event data types and include files command line options. --- .../src/xyz/colinholzman/makina/CliOptions.kt | 11 ++- .../xyz/colinholzman/makina/CodeGenerator.kt | 13 +++- .../src/xyz/colinholzman/makina/Main.kt | 3 +- .../colinholzman/makina/CodeGeneratorTest.kt | 15 ++-- .../test/xyz/colinholzman/makina/MainTest.kt | 69 ++++++++++++++++--- 5 files changed, 87 insertions(+), 24 deletions(-) diff --git a/makina-compiler/src/xyz/colinholzman/makina/CliOptions.kt b/makina-compiler/src/xyz/colinholzman/makina/CliOptions.kt index b513241..ce0a614 100644 --- a/makina-compiler/src/xyz/colinholzman/makina/CliOptions.kt +++ b/makina-compiler/src/xyz/colinholzman/makina/CliOptions.kt @@ -7,7 +7,16 @@ class CliOptions { @Option(names = ["-o", "--output"], description = ["generated files output directory"]) var outputDir: String? = null + @Option(names = ["-m", "--machine-data"], description = ["data type of machine context"]) + var machineDataType: String = "void *" + + @Option(names = ["-e", "--event-data"], description = ["data type of event context"]) + var eventDataType: String = "void *" + + @Option(names = ["-i", "--include"], description = ["files to include in generated code"]) + var includes: List = emptyList() + @Parameters(description = ["one ore more input files"]) - lateinit var files: List + var files: List = emptyList() } \ No newline at end of file diff --git a/makina-compiler/src/xyz/colinholzman/makina/CodeGenerator.kt b/makina-compiler/src/xyz/colinholzman/makina/CodeGenerator.kt index 32f0d79..4f71067 100644 --- a/makina-compiler/src/xyz/colinholzman/makina/CodeGenerator.kt +++ b/makina-compiler/src/xyz/colinholzman/makina/CodeGenerator.kt @@ -2,7 +2,10 @@ package xyz.colinholzman.makina import java.io.PrintWriter -class CodeGenerator(val machine: Machine) { +class CodeGenerator(val machine: Machine, + val machineDataType: String = "void *", + val eventDataType: String = "void *", + val includes: List = emptyList()) { private val machineStructName = "struct ${machine.id}" private val machineEventName = "struct ${machine.id}_event" @@ -14,6 +17,10 @@ class CodeGenerator(val machine: Machine) { println("#ifndef ${machine.id.toUpperCase()}_H") println("#define ${machine.id.toUpperCase()}_H") println() + for (include in includes) { + println("#include \"$include\"") + } + println() println("$machineStructName;") println("$machineEventName;") println() @@ -28,13 +35,13 @@ class CodeGenerator(val machine: Machine) { println("};") println() println("$machineEventName {") + println("\t${eventDataType} ctx;") println("\t$machineEventIdName id;") - println("\tvoid *ctx;") println("};") println() println("$machineStructName {") println("\tint (*state)($machineStructName *, $machineEventName *);") - println("\tvoid *ctx;") + println("\t${machineDataType} ctx;") println("};") println() println("int ${machine.id}_init($machineStructName *);") diff --git a/makina-compiler/src/xyz/colinholzman/makina/Main.kt b/makina-compiler/src/xyz/colinholzman/makina/Main.kt index 1e56d34..16cf83b 100644 --- a/makina-compiler/src/xyz/colinholzman/makina/Main.kt +++ b/makina-compiler/src/xyz/colinholzman/makina/Main.kt @@ -22,7 +22,8 @@ fun main(args: Array) { val headerPath = Paths.get(outputDirectoryPath, "${machine.id}.h").toString() val sourcePath = Paths.get(outputDirectoryPath, "${machine.id}.c").toString() - val generator = CodeGenerator(machine) + val generator = CodeGenerator(machine, options.machineDataType, + options.eventDataType, options.includes) val headerStream = ByteArrayOutputStream() val implementationStream = ByteArrayOutputStream() diff --git a/makina-compiler/test/xyz/colinholzman/makina/CodeGeneratorTest.kt b/makina-compiler/test/xyz/colinholzman/makina/CodeGeneratorTest.kt index f3538de..a7b76a6 100644 --- a/makina-compiler/test/xyz/colinholzman/makina/CodeGeneratorTest.kt +++ b/makina-compiler/test/xyz/colinholzman/makina/CodeGeneratorTest.kt @@ -116,14 +116,14 @@ internal class CodeGeneratorTest { int main (void) { output = fopen("test_output.txt", "w+"); struct test instance; - test_init(&instance); //s1_entry, s1_s2_entry - test_process_event(&instance, &(struct test_event) {test_event_e1}); //s1_s2_e1_guard, s1_s2_exit, s1_exit, s2_entry, s2_s1_entry - test_process_event(&instance, &(struct test_event) {test_event_e2}); //... - test_process_event(&instance, &(struct test_event) {test_event_e1}); //s2_s1_exit, s2_exit, s2_s1_e1_action, s1_entry, s1_s2_entry + test_init(&instance); //s1_entry, s1_s2_entry + test_process_event(&instance, &(struct test_event) {.id = test_event_e1}); //s1_s2_e1_guard, s1_s2_exit, s1_exit, s2_entry, s2_s1_entry + test_process_event(&instance, &(struct test_event) {.id = test_event_e2}); //... + test_process_event(&instance, &(struct test_event) {.id = test_event_e1}); //s2_s1_exit, s2_exit, s2_s1_e1_action, s1_entry, s1_s2_entry s1_s2_e1_guard_value = 1; - test_process_event(&instance, &(struct test_event) {test_event_e1}); //s1_s2_e1_guard, s1_s2_e1_action - test_process_event(&instance, &(struct test_event) {test_event_e2}); //s1_s2_exit, s1_exit, s2_entry, s2_s3_entry - test_process_event(&instance, &(struct test_event) {test_event_e2}); //s2_s3_exit, s2_exit, s1_entry, s1_s2_entry + test_process_event(&instance, &(struct test_event) {.id = test_event_e1}); //s1_s2_e1_guard, s1_s2_e1_action + test_process_event(&instance, &(struct test_event) {.id = test_event_e2}); //s1_s2_exit, s1_exit, s2_entry, s2_s3_entry + test_process_event(&instance, &(struct test_event) {.id = test_event_e2}); //s2_s3_exit, s2_exit, s1_entry, s1_s2_entry fclose(output); return 0; } @@ -165,7 +165,6 @@ internal class CodeGeneratorTest { //invoke Makina main(arrayOf(testSourceFile.absolutePath)) - val makinaOutputFilePath = testDir.resolve("test.c").toString() val compiledExecutablePath = testDir.resolve("test.exe").toString() diff --git a/makina-compiler/test/xyz/colinholzman/makina/MainTest.kt b/makina-compiler/test/xyz/colinholzman/makina/MainTest.kt index b093cbe..69d905e 100644 --- a/makina-compiler/test/xyz/colinholzman/makina/MainTest.kt +++ b/makina-compiler/test/xyz/colinholzman/makina/MainTest.kt @@ -8,32 +8,79 @@ class MainTest { @Test fun main() { - val sourceFile = File.createTempFile("makina", ".mkna") val name = "foo" + val sourceFile = File.createTempFile("makina", ".mkna") sourceFile.writeText("machine $name; state bar {}") - main(arrayOf(sourceFile.absolutePath)) + val header = File(Paths.get(sourceFile.parent, "$name.h").toUri()) val implementation = File(Paths.get(sourceFile.parent, "$name.c").toUri()) + + if (header.exists()) header.deleteRecursively() + if (implementation.exists()) implementation.deleteRecursively() + + main(arrayOf(sourceFile.absolutePath)) assert(header.exists()) assert(implementation.exists()) } @Test fun outputDirectory() { - val sourceFile = File.createTempFile("makina", ".mkna") val name = "foo" + val sourceFile = File.createTempFile("makina", ".mkna") sourceFile.writeText("machine $name; state bar {}") + val outputDirectoryName = "test" - val outputDir = Paths.get(sourceFile.parent, outputDirectoryName).toString() - val outputDirFile = File(outputDir) - if (outputDirFile.exists()) { - outputDirFile.deleteRecursively() - } - main(arrayOf(sourceFile.absolutePath, "-o", outputDir)) - val header = File(Paths.get(outputDir, "$name.h").toUri()) - val implementation = File(Paths.get(outputDir, "$name.c").toUri()) + val outputDirPath = Paths.get(sourceFile.parent, outputDirectoryName).toString() + + val header = File(Paths.get(outputDirPath, "$name.h").toUri()) + val implementation = File(Paths.get(outputDirPath, "$name.c").toUri()) + + if (header.exists()) header.deleteRecursively() + if (implementation.exists()) implementation.deleteRecursively() + + val outputDir = File(outputDirPath) + if (outputDir.exists()) outputDir.deleteRecursively() + + main(arrayOf(sourceFile.absolutePath, "-o", outputDirPath)) + assert(header.exists()) assert(implementation.exists()) } + @Test + fun dataTypes() { + val name = "foo" + val sourceFile = File.createTempFile("makina", ".mkna") + sourceFile.writeText("machine $name; state bar {}") + + val header = File(Paths.get(sourceFile.parent, "$name.h").toUri()) + if (header.exists()) header.deleteRecursively() + + val machineDataType = "struct machine_data" + val eventDataType = "struct event_data" + main(arrayOf(sourceFile.absolutePath, "-m", machineDataType, "-e", eventDataType)) + + val headerContent = header.readBytes().toString(Charsets.UTF_8) + assert(headerContent.contains("$machineDataType ctx;")) + assert(headerContent.contains("$eventDataType ctx;")) + } + + @Test + fun includes() { + val name = "foo" + val sourceFile = File.createTempFile("makina", ".mkna") + sourceFile.writeText("machine $name; state bar {}") + + val header = File(Paths.get(sourceFile.parent, "$name.h").toUri()) + if (header.exists()) header.deleteRecursively() + + val include1 = "../some_header.h" + val include2 = "another_header.h" + main(arrayOf(sourceFile.absolutePath, "-i", include1, "-i", include2)) + + val headerContent = header.readBytes().toString(Charsets.UTF_8) + assert(headerContent.contains("#include \"$include1\"")) + assert(headerContent.contains("#include \"$include2\"")) + } + } \ No newline at end of file