package org.shedlang.compiler.shid; import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.typed.*; import org.shedlang.compiler.shid.instructions.*; 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; import static org.zwobble.precisely.Matchers.*; public class ShidCodeGenNamespaceTests { @Test public void bodyOfNamespaceIsCompiledWithNamesBeingExported() { var namespaceName = new NamespaceName(List.of("Example")); var node = Typed.namespace( namespaceName, List.of( TypedFunctionDefinitionNode.builder() .withName("f") .addPositionalParam("x", Typed.typeLevelReference("String", Types.STRING)) .addNamedParam("y", Typed.typeLevelReference("Int", Types.INT)) .addStatement(Typed.expressionStatement(Typed.stringLiteral("hello"))) .build() ), List.of(BoundVariable.val("f")), List.of("f") ); var shidNamespace = ShidCodeGen.compileNamespace(node); assertThat(shidNamespace.body(), isShidBlock(isSequence( // TODO: test the builtin loading properly instanceOf(ShidNamespaceImport.class), instanceOf(ShidFieldLoad.class), instanceOf(ShidLocalStore.class), instanceOf( ShidDefineFunction.class, has("name", x -> x.name(), equalTo("f")) ), isShidLocalStore("f__0"), isShidLocalLoad("f__0"), isShidNamespaceFieldStore(namespaceName, "f") ))); } @Test public void importsAreLoaded() { var node = TypedNamespaceNode.builder() .addImport(Typed.import_(NamespaceName.of("A"))) .addBoundVariable(BoundVariable.val("A")) .addImport(Typed.import_(NamespaceName.of("B"))) .addBoundVariable(BoundVariable.val("B")) .build(); var shidNamespace = ShidCodeGen.compileNamespace(node); assertThat(shidNamespace.body(), isShidBlock(isSequence( // TODO: test the builtin loading properly instanceOf(ShidNamespaceImport.class), instanceOf(ShidFieldLoad.class), instanceOf(ShidLocalStore.class), isShidNamespaceImport(NamespaceName.of("A")), isShidLocalStore("A__0"), isShidNamespaceImport(NamespaceName.of("B")), isShidLocalStore("B__0") ))); } @Test public void structsAreHoisted() { var namespaceName = new NamespaceName(List.of("Example")); var structType = Types.struct(namespaceName, "None"); var node = Typed.namespace( namespaceName, List.of( TypedFunctionDefinitionNode.builder() .withName("f") .build(), TypedStructDefinitionNode.builder() .withType(structType) .build() ), List.of(BoundVariable.val("f"), BoundVariable.val("None")), List.of("f", "None") ); var shidNamespace = ShidCodeGen.compileNamespace(node); assertThat(shidNamespace.body(), isShidBlock(isSequence( // TODO: test the builtin loading properly instanceOf(ShidNamespaceImport.class), instanceOf(ShidFieldLoad.class), instanceOf(ShidLocalStore.class), instanceOf( ShidDefineStruct.class, has("type", x -> x.type(), equalTo(structType)) ), isShidLocalStore("None__0"), instanceOf( ShidDefineFunction.class, has("name", x -> x.name(), equalTo("f")) ), isShidLocalStore("f__0"), isShidLocalLoad("f__0"), isShidNamespaceFieldStore(namespaceName, "f"), isShidLocalLoad("None__0"), 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")) ), isShidMethodStore(structType, "name") ))); } }