aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-12-21 10:40:28 +0000
committerMichael Williamson <mike@zwobble.org>2024-12-21 10:40:28 +0000
commit2dba29dfa74c32a3102a9317455e16cd9a5a35a7 (patch)
tree6cee1e7886c35305ae24df5ba00c759dfe828d01 /src
parentf570b54bd3e0fe6ebc134101e3c54be5bc49253d (diff)
Compile methods into free functions
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java65
-rw-r--r--src/main/java/org/shedlang/compiler/shid/instructions/ShidDefineStruct.java4
-rw-r--r--src/test/java/org/shedlang/compiler/shid/ShidCodeGenNamespaceTests.java44
-rw-r--r--src/test/java/org/shedlang/compiler/shid/ShidCodeGenStructDefinitionTests.java18
-rw-r--r--src/test/java/org/shedlang/compiler/shid/instructions/Shid.java1
5 files changed, 97 insertions, 35 deletions
diff --git a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
index b0c33578..280e94b8 100644
--- a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java
@@ -474,6 +474,12 @@ public class ShidCodeGen {
for (var statement : statementsAfterHoisting) {
context = compileNamespaceStatement(statement, context);
}
+ for (var statement : statementsAfterHoisting) {
+ if (statement instanceof TypedStructDefinitionNode structDefinitionNode) {
+ // TODO: test method hoisting
+ context = compileStructDefinitionMethods(structDefinitionNode, context);
+ }
+ }
for (var fieldName : node.fieldNames()) {
var localName = context.shedVariableToLocal(fieldName);
@@ -549,31 +555,11 @@ public class ShidCodeGen {
) {
var structType = node.typeOrConstructor().toType();
- var methods = new ArrayList<ShidDefineStruct.Method>();
- for (var methodNode : node.methods()) {
- var shidFunctionName = context.generateLocalNameForVariable(
- structType.name() + "__" + methodNode.name()
- );
- context = compileFunction(
- shidFunctionName,
- methodNode.signature().params(),
- methodNode.body(),
- ShidDefineFunction.Variant.FUNCTION,
- methodNode.source(),
- context
- );
- methods.add(new ShidDefineStruct.Method(
- methodNode.name(),
- shidFunctionName
- ));
- }
-
var defineStructInstruction = new ShidDefineStruct(
structType,
node.fields().stream()
.map(field -> new ShidDefineStruct.Field(field.name(), field.source()))
.toList(),
- methods,
node.source()
);
@@ -585,6 +571,45 @@ public class ShidCodeGen {
.addInstruction(storeInstruction);
}
+ static Context compileStructDefinitionMethods(
+ TypedStructDefinitionNode node,
+ Context context
+ ) {
+ var structType = node.typeOrConstructor().toType();
+
+ for (var methodNode : node.methods()) {
+ var shidFunctionName = context.generateLocalNameForVariable(
+ "$methods__" + String.join("_", structType.namespaceName().parts()) + "__" + structType.name() + "__" + methodNode.name()
+ );
+ context = compileFunction(
+ shidFunctionName,
+ methodNode.signature().params(),
+ methodNode.body(),
+ ShidDefineFunction.Variant.FUNCTION,
+ methodNode.source(),
+ context
+ );
+
+ context = context.addInstruction(
+ new ShidLocalStore(shidFunctionName, methodNode.source())
+ );
+
+ context = context.addInstruction(
+ new ShidLocalLoad(shidFunctionName, methodNode.source())
+ );
+
+ context = context.addInstruction(
+ new ShidNamespaceFieldStore(
+ structType.namespaceName(),
+ shidFunctionName,
+ methodNode.source()
+ )
+ );
+ }
+
+ return context;
+ }
+
private static Context compileSumTypeDefinition(
TypedSumTypeDefinitionNode node,
Context context
diff --git a/src/main/java/org/shedlang/compiler/shid/instructions/ShidDefineStruct.java b/src/main/java/org/shedlang/compiler/shid/instructions/ShidDefineStruct.java
index c76b4f20..d3ed9e10 100644
--- a/src/main/java/org/shedlang/compiler/shid/instructions/ShidDefineStruct.java
+++ b/src/main/java/org/shedlang/compiler/shid/instructions/ShidDefineStruct.java
@@ -13,15 +13,11 @@ public record ShidDefineStruct(
SimpleStructType type,
// TODO: remove fields? We should have fields from the type info.
List<Field> fields,
- List<Method> methods,
Source source
) implements ShidInstruction {
public record Field(String name, Source source) {
}
- public record Method(String methodName, String shidFunctionName) {
- }
-
@Override
public boolean isBlockTerminator() {
return false;
diff --git a/src/test/java/org/shedlang/compiler/shid/ShidCodeGenNamespaceTests.java b/src/test/java/org/shedlang/compiler/shid/ShidCodeGenNamespaceTests.java
index 1e6a1000..e760bdae 100644
--- a/src/test/java/org/shedlang/compiler/shid/ShidCodeGenNamespaceTests.java
+++ b/src/test/java/org/shedlang/compiler/shid/ShidCodeGenNamespaceTests.java
@@ -7,6 +7,7 @@ import org.shedlang.compiler.types.NamespaceName;
import org.shedlang.compiler.types.Types;
import java.util.List;
+import java.util.Optional;
import static org.shedlang.compiler.shid.instructions.ShidMatchers.*;
import static org.zwobble.precisely.AssertThat.assertThat;
@@ -115,4 +116,47 @@ public class ShidCodeGenNamespaceTests {
isShidNamespaceFieldStore(namespaceName, "None")
)));
}
+
+ @Test
+ public void structMethodsAreExported() {
+ var namespaceName = new NamespaceName(List.of("Example", "Project"));
+ var structType = Types.struct(namespaceName, "User");
+ var node = Typed.namespace(
+ namespaceName,
+ List.of(
+ TypedStructDefinitionNode.builder()
+ .withType(structType)
+ .addMethod(
+ TypedFunctionDefinitionNode.builder()
+ .withName("name")
+ .addPositionalParam("this", Optional.empty())
+ .build()
+ )
+ .build()
+ ),
+ List.of(BoundVariable.val("User")),
+ List.of()
+ );
+
+ var shidNamespace = ShidCodeGen.compileNamespace(node);
+
+ assertThat(shidNamespace.body(), isShidBlock(isSequence(
+ instanceOf(ShidNamespaceImport.class),
+ instanceOf(ShidFieldLoad.class),
+ instanceOf(ShidLocalStore.class),
+
+ instanceOf(
+ ShidDefineStruct.class,
+ has("type", x -> x.type(), equalTo(structType))
+ ),
+ isShidLocalStore("User__0"),
+ instanceOf(
+ ShidDefineFunction.class,
+ has("name", x -> x.name(), equalTo("$methods__Example_Project__User__name__0"))
+ ),
+ isShidLocalStore("$methods__Example_Project__User__name__0"),
+ isShidLocalLoad("$methods__Example_Project__User__name__0"),
+ isShidNamespaceFieldStore(namespaceName, "$methods__Example_Project__User__name__0")
+ )));
+ }
}
diff --git a/src/test/java/org/shedlang/compiler/shid/ShidCodeGenStructDefinitionTests.java b/src/test/java/org/shedlang/compiler/shid/ShidCodeGenStructDefinitionTests.java
index 7db25429..0ffea260 100644
--- a/src/test/java/org/shedlang/compiler/shid/ShidCodeGenStructDefinitionTests.java
+++ b/src/test/java/org/shedlang/compiler/shid/ShidCodeGenStructDefinitionTests.java
@@ -61,12 +61,12 @@ public class ShidCodeGenStructDefinitionTests {
var context = ShidCodeGen.Context.EMPTY
.addShedVal("User");
- var result = ShidCodeGen.compileNamespaceStatement(node, context);
+ var result = ShidCodeGen.compileStructDefinitionMethods(node, context);
assertThat(result.instructions(), isSequence(
instanceOf(
ShidDefineFunction.class,
- has("name", x -> x.name(), equalTo("User__name__0")),
+ has("name", x -> x.name(), equalTo("$methods__Example_Project__User__name__0")),
has("positionalParams", x -> x.positionalParams(), isSequence(
isShidDefineFunctionParam("this__0"),
isShidDefineFunctionParam("a__0")
@@ -80,14 +80,12 @@ public class ShidCodeGenStructDefinitionTests {
isShidReturn()
)))
),
- instanceOf(
- ShidDefineStruct.class,
- has("type", x -> x.type(), equalTo(structType)),
- has("methods", x -> x.methods(), isSequence(
- equalTo(new ShidDefineStruct.Method("name", "User__name__0"))
- ))
- ),
- isShidLocalStore("User__0")
+ isShidLocalStore("$methods__Example_Project__User__name__0"),
+ isShidLocalLoad("$methods__Example_Project__User__name__0"),
+ isShidNamespaceFieldStore(
+ NamespaceName.of("Example", "Project"),
+ "$methods__Example_Project__User__name__0"
+ )
));
}
}
diff --git a/src/test/java/org/shedlang/compiler/shid/instructions/Shid.java b/src/test/java/org/shedlang/compiler/shid/instructions/Shid.java
index 1a547eea..ee78a3e3 100644
--- a/src/test/java/org/shedlang/compiler/shid/instructions/Shid.java
+++ b/src/test/java/org/shedlang/compiler/shid/instructions/Shid.java
@@ -35,7 +35,6 @@ public class Shid {
return new ShidDefineStruct(
type,
fields,
- List.of(),
Sources.NULL
);
}