diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-06-10 20:50:15 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-06-10 20:50:15 +0100 |
| commit | 0cf3c519c2b834c1d5709e1e98be54cd98b90eb9 (patch) | |
| tree | 8c3a56e24d9029c2a2410c00541da05c14457bee /src/main/java/org/shedlang/compiler/stackir | |
| parent | 4564de5f2b387ce71c906d980eb9d9ef2f5c4390 (diff) | |
Add serialization for instructions
Diffstat (limited to 'src/main/java/org/shedlang/compiler/stackir')
| -rw-r--r-- | src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java | 208 | ||||
| -rw-r--r-- | src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java | 4 |
2 files changed, 210 insertions, 2 deletions
diff --git a/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java b/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java new file mode 100644 index 00000000..65f29512 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java @@ -0,0 +1,208 @@ +package org.shedlang.compiler.stackir; + +import org.shedlang.compiler.stackir.instructions.*; + +import java.util.Arrays; +import java.util.List; + +import static org.shedlang.compiler.util.Iterables.forEachInterspersed; + +public class InstructionSerializer { + private InstructionSerializer() { + } + + public static void serialize(Instruction instruction, StringBuilder builder) { + var tree = toTree(instruction); + serializeTree(tree, builder, 0); + } + + private static Tree toTree(Instruction instruction) { + return switch (instruction) { + case CallInstruction callInstruction -> + treeList( + treeIdentifier("call"), + treeNamed( + "positionalArgCount", + treeInt(callInstruction.positionalArgCount()) + ), + treeNamed( + "namedArgNames", + treeList( + callInstruction.namedArgNames().stream() + .map(arg -> treeString(arg)) + .toList() + ) + ) + ); + + case DefineFunctionInstruction defineFunctionInstruction -> + treeListIndented( + treeIdentifier("define-function"), + treeNamed("positionalParams", treeList( + defineFunctionInstruction.positionalParams().stream() + .map(param -> treeString(param.name())) + .toList() + )), + treeNamed("namedParams", treeList( + defineFunctionInstruction.namedParams().stream() + .map(param -> treeString(param.name())) + .toList() + )), + treeNamed("freeVariables", treeList( + defineFunctionInstruction.freeVariables().stream() + .map(freeVariable -> treeString(freeVariable)) + .toList() + )), + treeNamed("body", treeListIndented( + defineFunctionInstruction.body().stream() + .map(bodyInstruction -> toTree(bodyInstruction)) + .toList() + )) + ); + + case DiscardInstruction discardInstruction -> + treeList( + treeIdentifier("discard") + ); + + case LocalLoadInstruction localLoadInstruction -> + treeList( + treeIdentifier("local-load"), + treeString(localLoadInstruction.name()) + ); + + case LocalStoreInstruction localStoreInstruction -> + treeList( + treeIdentifier("local-store"), + treeString(localStoreInstruction.name()) + ); + + case ModuleExportInstruction moduleExportInstruction -> + treeList( + treeIdentifier("module-export"), + treeString(moduleExportInstruction.name()) + ); + + case PushBoolInstruction pushBoolInstruction -> + treeList( + treeIdentifier("push-bool"), + treeIdentifier(Boolean.toString(pushBoolInstruction.value())) + ); + + case PushIntInstruction pushIntInstruction -> + treeList( + treeIdentifier("push-int"), + treeIdentifier(pushIntInstruction.value().toString()) + ); + + case PushStringInstruction pushStringInstruction -> + treeList( + treeIdentifier("push-string"), + treeString(pushStringInstruction.value()) + ); + }; + } + + private static Tree treeIdentifier(String name) { + return new TreeIdentifier(name); + } + + private static Tree treeInt(int value) { + return new TreeInt(value); + } + + private static Tree treeList(List<Tree> children) { + return new TreeList(children); + } + + private static Tree treeList(Tree... children) { + return new TreeList(Arrays.asList(children)); + } + + private static Tree treeListIndented(List<Tree> children) { + return new TreeListIndented(children); + } + + private static Tree treeListIndented(Tree... children) { + return new TreeListIndented(Arrays.asList(children)); + } + + private static Tree treeNamed(String name, Tree value) { + return new TreeNamed(name, value); + } + + private static Tree treeString(String value) { + return new TreeString(value); + } + + private sealed interface Tree {} + + private record TreeIdentifier(String name) implements Tree { + } + + private record TreeInt(int value) implements Tree { + } + + private record TreeList(List<Tree> children) implements Tree { + } + + private record TreeListIndented(List<Tree> children) implements Tree { + } + + private record TreeNamed(String name, Tree value) implements Tree { + } + + private record TreeString(String value) implements Tree { + } + + private static void serializeTree(Tree tree, StringBuilder builder, int indentation) { + switch (tree) { + case TreeIdentifier identifier -> { + builder.append(identifier.name); + } + case TreeInt treeInt -> { + builder.append(treeInt.value); + } + case TreeList list -> { + builder.append("("); + forEachInterspersed( + list.children, + child -> serializeTree(child, builder, indentation), + () -> builder.append(" ") + ); + builder.append(")"); + } + case TreeListIndented list -> { + builder.append("("); + forEachInterspersed( + list.children, + child -> { + newLine(indentation + 1, builder); + serializeTree(child, builder, indentation + 1); + }, + () -> {} + ); + newLine(indentation, builder); + builder.append(")"); + } + case TreeNamed named -> { + builder.append(named.name); + builder.append("="); + serializeTree(named.value, builder, indentation); + } + case TreeString string -> { + // TODO: escaping + builder.append("\""); + builder.append(string.value); + builder.append("\""); + } + } + } + + private static void newLine(int indentation, StringBuilder builder) { + builder.append("\n"); + for (var i = 0; i < indentation; i++) { + builder.append(" "); + } + } +} diff --git a/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java b/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java index 1cdfa9d5..d1e3c4bb 100644 --- a/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java +++ b/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java @@ -5,8 +5,8 @@ import org.shedlang.compiler.sources.Source; import java.util.List; public record CallInstruction( - int argCount, - List<String> namedArgs, + int positionalArgCount, + List<String> namedArgNames, Source source ) implements Instruction { } |
