aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-12-22 10:36:51 +0000
committerMichael Williamson <mike@zwobble.org>2024-12-22 10:36:51 +0000
commita38bd5d597471e2ee434271fa7a82b835e828062 (patch)
tree7d2203893cc8cb14f7811c37808954c2fcc279f3 /src
parent35b78f02a0808e420e0f040f44c649b7354cd49d (diff)
Handle params in method references
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java53
-rw-r--r--src/test/java/org/shedlang/compiler/shid/ShidCodeGenMemberAccessTests.java57
2 files changed, 99 insertions, 11 deletions
diff --git a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
index 1fe776d4..d6626b37 100644
--- a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
@@ -13,6 +13,7 @@ import org.shedlang.compiler.util.P;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Stream;
public class ShidCodeGen {
private ShidCodeGen() {
@@ -407,6 +408,8 @@ public class ShidCodeGen {
case METHOD -> {
// TODO: handle not a struct type
var structType = ((ShidFieldLoad.Receiver.Struct) receiver).type();
+ // TODO: handle not a function type
+ var methodType = (FunctionType) node.type();
var receiverLocalNameResult = context.generateShidVal("receiver");
var receiverLocalName = receiverLocalNameResult.value();
@@ -416,17 +419,59 @@ public class ShidCodeGen {
new ShidLocalStore(receiverLocalName, node.source())
);
- context = context.enterBlock(List.of(), node.source());
+ var shedPositionalParamNames = new ArrayList<String>();
+ for (
+ var positionalParamIndex = 0;
+ positionalParamIndex < methodType.positionalParams().size();
+ positionalParamIndex++
+ ) {
+ shedPositionalParamNames.add("arg" + positionalParamIndex);
+ }
+
+ var boundVariables = Stream.concat(
+ shedPositionalParamNames.stream(),
+ methodType.namedParams().stream()
+ .map(namedParam -> namedParam.name())
+ )
+ .map(BoundVariable::param)
+ .toList();
+
+ context = context.enterBlock(boundVariables, node.source());
context = context.addInstruction(
new ShidMethodLoad(structType, node.memberName(), node.source())
);
+
context = context.addInstruction(
new ShidLocalLoad(receiverLocalName, node.source())
);
+ var shidPositionalParams = new ArrayList<ShidDefineFunction.Param>();
+ for (var positionalParamName : shedPositionalParamNames) {
+ var shidParamName = context.shedVariableToLocal(positionalParamName);
+ shidPositionalParams.add(new ShidDefineFunction.Param(shidParamName, node.source()));
+ context = context.addInstruction(
+ new ShidLocalLoad(shidParamName, node.source())
+ );
+ }
+
+ var shidNamedParams = new ArrayList<ShidDefineFunction.Param>();
+ for (var namedParam : methodType.namedParams()) {
+ var shidParamName = context.shedVariableToLocal(namedParam.name());
+ shidNamedParams.add(new ShidDefineFunction.Param(shidParamName, node.source()));
+ context = context.addInstruction(
+ new ShidLocalLoad(shidParamName, node.source())
+ );
+ }
+
context = context.addInstruction(
- new ShidCall(1, List.of(), node.source())
+ new ShidCall(
+ methodType.positionalParams().size() + 1,
+ methodType.namedParams().stream()
+ .map(namedParam -> namedParam.name())
+ .toList(),
+ node.source()
+ )
);
context = context.addInstruction(new ShidReturn(node.source()));
@@ -438,8 +483,8 @@ public class ShidCodeGen {
yield context.addInstruction(
new ShidDefineFunction(
node.memberName(),
- List.of(),
- List.of(),
+ shidPositionalParams,
+ shidNamedParams,
FreeVariables.builder()
.plus(receiverLocalName, node.source())
.build(),
diff --git a/src/test/java/org/shedlang/compiler/shid/ShidCodeGenMemberAccessTests.java b/src/test/java/org/shedlang/compiler/shid/ShidCodeGenMemberAccessTests.java
index 79453d76..d2a0e5ce 100644
--- a/src/test/java/org/shedlang/compiler/shid/ShidCodeGenMemberAccessTests.java
+++ b/src/test/java/org/shedlang/compiler/shid/ShidCodeGenMemberAccessTests.java
@@ -5,10 +5,7 @@ import org.shedlang.compiler.ast.typed.Typed;
import org.shedlang.compiler.shid.instructions.ShidDefineFunction;
import org.shedlang.compiler.shid.instructions.ShidFieldLoad;
import org.shedlang.compiler.shid.instructions.ShidMatchers;
-import org.shedlang.compiler.types.Effects;
-import org.shedlang.compiler.types.NamespaceName;
-import org.shedlang.compiler.types.TypeParam;
-import org.shedlang.compiler.types.Types;
+import org.shedlang.compiler.types.*;
import java.util.List;
@@ -60,13 +57,15 @@ public class ShidCodeGenMemberAccessTests {
}
@Test
- public void structMethodAccessIsCompiledToDefineFunctionInstruction() {
+ public void structMethodAccessZeroParamsIsCompiledToDefineFunctionInstruction() {
var namespaceName = NamespaceName.of("Example", "Project");
var structType = Types.struct(namespaceName, "User");
var node = Typed.methodAccess(
Typed.reference("user", structType),
"name",
- Types.STRING
+ FunctionType.builder()
+ .withReturnType(Types.STRING)
+ .build()
);
var context = ShidCodeGen.Context.EMPTY
.addShedVal("user");
@@ -74,7 +73,6 @@ public class ShidCodeGenMemberAccessTests {
var result = ShidCodeGen.compileExpression(node, context);
// TODO: optimise calls
- // TODO: handle params
assertThat(result.instructions(), isSequence(
isShidLocalLoad("user__0"),
isShidLocalStore("receiver__0"),
@@ -97,6 +95,51 @@ public class ShidCodeGenMemberAccessTests {
}
@Test
+ public void structMethodAccessMultipleParamsIsCompiledToDefineFunctionInstruction() {
+ var namespaceName = NamespaceName.of("Example", "Project");
+ var structType = Types.struct(namespaceName, "User");
+ var node = Typed.methodAccess(
+ Typed.reference("user", structType),
+ "name",
+ FunctionType.builder()
+ .addPositionalParam(Types.BOOL)
+ .addNamedParam("b", Types.INT)
+ .withReturnType(Types.STRING)
+ .build()
+ );
+ var context = ShidCodeGen.Context.EMPTY
+ .addShedVal("user");
+
+ var result = ShidCodeGen.compileExpression(node, context);
+
+ assertThat(result.instructions(), isSequence(
+ isShidLocalLoad("user__0"),
+ isShidLocalStore("receiver__0"),
+ instanceOf(
+ ShidDefineFunction.class,
+ has("name", x -> x.name(), equalTo("name")),
+ has("positionalParams", x -> x.positionalParams(), isSequence(
+ isShidDefineFunctionParam("arg0__0")
+ )),
+ has("namedParams", x -> x.namedParams(), isSequence(
+ isShidDefineFunctionParam("b__0")
+ )),
+ has("freeVariables", x -> x.freeVariables(), containsExactly(
+ has("user", x -> x.name(), equalTo("receiver__0"))
+ )),
+ has("body", x -> x.body(), isShidBlock(isSequence(
+ isShidMethodLoad(structType, "name"),
+ isShidLocalLoad("receiver__0"),
+ isShidLocalLoad("arg0__0"),
+ isShidLocalLoad("b__0"),
+ isShidCall(2, List.of("b")),
+ isShidReturn()
+ )))
+ )
+ ));
+ }
+
+ @Test
public void constructedTypeFieldAccessIsCompiledToFieldLoad() {
var structType = Types.struct(NamespaceName.of("Example", "Project"), "Box");
var typeConstructor = Types.typeConstructor(