aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-06-10 11:52:04 +0100
committerMichael Williamson <mike@zwobble.org>2023-06-10 11:52:04 +0100
commit2cefa82d059dfd16d224b16f92fd69104beb24a2 (patch)
tree17379341465e719747c0d230778b3624cc233dc3 /src
parentd1d9c3800ab56b3c825f72e3e997b0521cfac9ce (diff)
Compile calls to stack instructions
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/stackir/StackCompiler.java48
-rw-r--r--src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java12
-rw-r--r--src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java3
-rw-r--r--src/main/java/org/shedlang/compiler/util/P.java8
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/Typed.java19
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java40
-rw-r--r--src/test/java/org/shedlang/compiler/stackir/StackCompilerCallTests.java39
-rw-r--r--src/test/java/org/shedlang/compiler/stackir/instructions/InstructionMatchers.java9
8 files changed, 145 insertions, 33 deletions
diff --git a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
index 1d6b0a88..c16674e0 100644
--- a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
+++ b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
@@ -1,25 +1,49 @@
package org.shedlang.compiler.stackir;
+import org.pcollections.PVector;
import org.shedlang.compiler.ast.typed.*;
import org.shedlang.compiler.stackir.instructions.*;
-
-import java.util.List;
+import org.shedlang.compiler.util.P;
public class StackCompiler {
private StackCompiler() {
}
- private static List<Instruction> compileBoolLiteral(TypedBoolLiteralNode node) {
- return List.of(new PushBoolInstruction(node.value(), node.source()));
+ private static PVector<Instruction> compileBoolLiteral(TypedBoolLiteralNode node) {
+ return P.vector(new PushBoolInstruction(node.value(), node.source()));
+ }
+
+ private static PVector<Instruction> compileCall(TypedCallNode node) {
+ var instructions = compileExpression(node.receiver());
+
+ instructions = node.args().positional().stream()
+ .map(arg -> compileExpression(arg))
+ .reduce(instructions, PVector::plusAll);
+
+ instructions = node.args().named().stream()
+ .map(arg -> compileExpression(arg.expression()))
+ .reduce(instructions, PVector::plusAll);
+
+ var callInstruction = new CallInstruction(
+ node.args().positional().size(),
+ node.args().named().stream()
+ .map(arg -> arg.name())
+ .toList(),
+ node.source()
+ );
+
+ instructions = instructions.plus(callInstruction);
+
+ return instructions;
}
- public static List<Instruction> compileExpression(TypedExpressionNode node) {
+ public static PVector<Instruction> compileExpression(TypedExpressionNode node) {
return switch (node) {
case TypedBoolLiteralNode typedBoolLiteralNode ->
compileBoolLiteral(typedBoolLiteralNode);
case TypedCallNode typedCallNode ->
- throw new UnsupportedOperationException("TODO");
+ compileCall(typedCallNode);
case TypedIntLiteralNode typedIntLiteralNode ->
compileIntLiteral(typedIntLiteralNode);
@@ -32,15 +56,15 @@ public class StackCompiler {
};
}
- private static List<Instruction> compileIntLiteral(TypedIntLiteralNode node) {
- return List.of(new PushIntInstruction(node.value(), node.source()));
+ private static PVector<Instruction> compileIntLiteral(TypedIntLiteralNode node) {
+ return P.vector(new PushIntInstruction(node.value(), node.source()));
}
- private static List<Instruction> compileReference(TypedReferenceNode node) {
- return List.of(new LocalLoadInstruction(node.name(), node.source()));
+ private static PVector<Instruction> compileReference(TypedReferenceNode node) {
+ return P.vector(new LocalLoadInstruction(node.name(), node.source()));
}
- private static List<Instruction> compileStringLiteral(TypedStringLiteralNode node) {
- return List.of(new PushStringInstruction(node.value(), node.source()));
+ private static PVector<Instruction> compileStringLiteral(TypedStringLiteralNode node) {
+ return P.vector(new PushStringInstruction(node.value(), node.source()));
}
}
diff --git a/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java b/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java
new file mode 100644
index 00000000..1cdfa9d5
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/stackir/instructions/CallInstruction.java
@@ -0,0 +1,12 @@
+package org.shedlang.compiler.stackir.instructions;
+
+import org.shedlang.compiler.sources.Source;
+
+import java.util.List;
+
+public record CallInstruction(
+ int argCount,
+ List<String> namedArgs,
+ Source source
+) implements Instruction {
+}
diff --git a/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java b/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java
index 59af2b9b..33007bf2 100644
--- a/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java
+++ b/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java
@@ -1,4 +1,5 @@
package org.shedlang.compiler.stackir.instructions;
-public sealed interface Instruction permits LocalLoadInstruction, LocalStoreInstruction, PushBoolInstruction, PushIntInstruction, PushStringInstruction {
+public sealed interface Instruction
+ permits CallInstruction, LocalLoadInstruction, LocalStoreInstruction, PushBoolInstruction, PushIntInstruction, PushStringInstruction {
}
diff --git a/src/main/java/org/shedlang/compiler/util/P.java b/src/main/java/org/shedlang/compiler/util/P.java
index 7ce8232c..a09d7940 100644
--- a/src/main/java/org/shedlang/compiler/util/P.java
+++ b/src/main/java/org/shedlang/compiler/util/P.java
@@ -2,7 +2,10 @@ package org.shedlang.compiler.util;
import org.pcollections.HashTreePMap;
import org.pcollections.PMap;
+import org.pcollections.PVector;
+import org.pcollections.TreePVector;
+import java.util.Arrays;
import java.util.Map;
public class P {
@@ -17,4 +20,9 @@ public class P {
}
return map;
}
+
+ @SafeVarargs
+ public static <T> PVector<T> vector(T... values) {
+ return TreePVector.from(Arrays.asList(values));
+ }
}
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/Typed.java b/src/test/java/org/shedlang/compiler/ast/typed/Typed.java
index 75f54d36..ed58b4d4 100644
--- a/src/test/java/org/shedlang/compiler/ast/typed/Typed.java
+++ b/src/test/java/org/shedlang/compiler/ast/typed/Typed.java
@@ -5,6 +5,7 @@ import org.shedlang.compiler.types.Type;
import org.shedlang.compiler.types.Types;
import java.math.BigInteger;
+import java.util.List;
public class Typed {
private Typed() {
@@ -14,10 +15,28 @@ public class Typed {
return new TypedBoolLiteralNode(value, Sources.NULL);
}
+ public static TypedCallNode call(
+ TypedExpressionNode receiver,
+ List<TypedExpressionNode> positionalArgs,
+ List<TypedNamedArgNode> namedArgs
+ ) {
+ return new TypedCallNode(
+ receiver,
+ new TypedArgsNode(positionalArgs, namedArgs, Sources.NULL),
+ false,
+ Types.UNIT,
+ Sources.NULL
+ );
+ }
+
public static TypedIntLiteralNode intLiteral(int value) {
return new TypedIntLiteralNode(BigInteger.valueOf(value), Sources.NULL);
}
+ public static TypedNamedArgNode namedArg(String name, TypedExpressionNode expression) {
+ return new TypedNamedArgNode(name, expression, Sources.NULL);
+ }
+
public static TypedStringLiteralNode stringLiteral(String value) {
return new TypedStringLiteralNode(value, Sources.NULL);
}
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
index 11e7b38f..5cc0ce85 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
@@ -13,26 +13,6 @@ public class Untyped {
return new UntypedBoolLiteralNode(value, Sources.NULL);
}
- public static UntypedIntLiteralNode intLiteral(int value) {
- return new UntypedIntLiteralNode(BigInteger.valueOf(value), Sources.NULL);
- }
-
- public static UntypedIntLiteralNode intLiteral(BigInteger value) {
- return new UntypedIntLiteralNode(value, Sources.NULL);
- }
-
- public static UntypedNamedArgNode namedArg(String name, UntypedExpressionNode expression) {
- return new UntypedNamedArgNode(name, expression, Sources.NULL);
- }
-
- public static UntypedReferenceNode reference(String name) {
- return new UntypedReferenceNode(name, Sources.NULL);
- }
-
- public static UntypedStringLiteralNode stringLiteral(String value) {
- return new UntypedStringLiteralNode(value, Sources.NULL);
- }
-
public static UntypedCallNode call(
UntypedExpressionNode receiver,
List<UntypedExpressionNode> positionalArgs
@@ -52,4 +32,24 @@ public class Untyped {
Sources.NULL
);
}
+
+ public static UntypedIntLiteralNode intLiteral(int value) {
+ return new UntypedIntLiteralNode(BigInteger.valueOf(value), Sources.NULL);
+ }
+
+ public static UntypedIntLiteralNode intLiteral(BigInteger value) {
+ return new UntypedIntLiteralNode(value, Sources.NULL);
+ }
+
+ public static UntypedNamedArgNode namedArg(String name, UntypedExpressionNode expression) {
+ return new UntypedNamedArgNode(name, expression, Sources.NULL);
+ }
+
+ public static UntypedReferenceNode reference(String name) {
+ return new UntypedReferenceNode(name, Sources.NULL);
+ }
+
+ public static UntypedStringLiteralNode stringLiteral(String value) {
+ return new UntypedStringLiteralNode(value, Sources.NULL);
+ }
}
diff --git a/src/test/java/org/shedlang/compiler/stackir/StackCompilerCallTests.java b/src/test/java/org/shedlang/compiler/stackir/StackCompilerCallTests.java
new file mode 100644
index 00000000..f4a2f229
--- /dev/null
+++ b/src/test/java/org/shedlang/compiler/stackir/StackCompilerCallTests.java
@@ -0,0 +1,39 @@
+package org.shedlang.compiler.stackir;
+
+import org.junit.jupiter.api.Test;
+import org.shedlang.compiler.ast.typed.Typed;
+
+import java.util.List;
+
+import static org.shedlang.compiler.stackir.instructions.InstructionMatchers.*;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.isSequence;
+
+public class StackCompilerCallTests {
+ @Test
+ public void callIsCompiledToInstructionsForOperandThenCall() {
+ var node = Typed.call(
+ Typed.reference("f"),
+ List.of(
+ Typed.stringLiteral("p1"),
+ Typed.stringLiteral("p2")
+
+ ),
+ List.of(
+ Typed.namedArg("x2", Typed.stringLiteral("n2")),
+ Typed.namedArg("x1", Typed.stringLiteral("n1"))
+ )
+ );
+
+ var instructions = StackCompiler.compileExpression(node);
+
+ assertThat(instructions, isSequence(
+ isLocalLoadInstruction("f"),
+ isPushStringInstruction("p1"),
+ isPushStringInstruction("p2"),
+ isPushStringInstruction("n2"),
+ isPushStringInstruction("n1"),
+ isCallInstruction(2, List.of("x2", "x1"))
+ ));
+ }
+}
diff --git a/src/test/java/org/shedlang/compiler/stackir/instructions/InstructionMatchers.java b/src/test/java/org/shedlang/compiler/stackir/instructions/InstructionMatchers.java
index 2fc1aa21..c9cd8621 100644
--- a/src/test/java/org/shedlang/compiler/stackir/instructions/InstructionMatchers.java
+++ b/src/test/java/org/shedlang/compiler/stackir/instructions/InstructionMatchers.java
@@ -3,6 +3,7 @@ package org.shedlang.compiler.stackir.instructions;
import org.zwobble.precisely.Matcher;
import java.math.BigInteger;
+import java.util.List;
import static org.zwobble.precisely.Matchers.*;
@@ -10,6 +11,14 @@ public class InstructionMatchers {
private InstructionMatchers() {
}
+ public static Matcher<Instruction> isCallInstruction(int argCount, List<String> namedArgs) {
+ return instanceOf(
+ CallInstruction.class,
+ has("argCount", x -> x.argCount(), equalTo(argCount)),
+ has("namedArgs", x -> x.namedArgs(), equalTo(namedArgs))
+ );
+ }
+
public static Matcher<Instruction> isLocalLoadInstruction(String name) {
return instanceOf(
LocalLoadInstruction.class,