package org.shedlang.compiler.shid; import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.typed.Typed; import org.shedlang.compiler.ast.typed.TypedFunctionDefinitionNode; import org.shedlang.compiler.ast.typed.TypedStructDefinitionNode; import org.shedlang.compiler.shid.instructions.ShidDefineFunction; import org.shedlang.compiler.shid.instructions.ShidDefineStruct; import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; 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 ShidCodeGenStructDefinitionTests { @Test public void structDefinitionIsCompiledToDefineStructInstruction() { var structType = Types.struct(NamespaceName.of("Example", "Project"), "User"); var node = TypedStructDefinitionNode.builder() .withType(structType) .addField(Typed.structFieldDefinition("name", Typed.typeLevelReference("String", Types.STRING))) .addField(Typed.structFieldDefinition("isActive", Typed.typeLevelReference("Bool", Types.BOOL))) .build(); var context = ShidCodeGen.Context.EMPTY .addShedVal("User"); var result = ShidCodeGen.compileNamespaceStatement(node, context); assertThat(result.instructions(), isSequence( instanceOf( ShidDefineStruct.class, has("type", x -> x.type(), equalTo(structType)), has("fields", x -> x.fields(), isSequence( has("name", x -> x.name(), equalTo("name")), has("name", x -> x.name(), equalTo("isActive")) )) ), isShidLocalStore("User__0") )); } @Test public void structMethodsAreCompiledToFreeFunctions() { var structType = Types.struct(NamespaceName.of("Example", "Project"), "User"); var node = TypedStructDefinitionNode.builder() .withType(structType) .addMethod( TypedFunctionDefinitionNode.builder() .withName("name") .addPositionalParam("this", Optional.empty()) .addPositionalParam("a", Typed.typeLevelReference("Bool", Types.BOOL)) .addNamedParam("b", Typed.typeLevelReference("Int", Types.INT)) .withReturnType(Typed.typeLevelReference("String", Types.STRING)) .addStatement(Typed.blockReturn(Typed.stringLiteral("hello"))) .build() ) .build(); var context = ShidCodeGen.Context.EMPTY .addShedVal("User"); var result = ShidCodeGen.compileStructDefinitionMethods(node, context); assertThat(result.instructions(), isSequence( instanceOf( ShidDefineFunction.class, has("name", x -> x.name(), equalTo("$methods__Example_Project__User__name")), has("positionalParams", x -> x.positionalParams(), isSequence( isShidDefineFunctionParam("this__0"), isShidDefineFunctionParam("a__0") )), has("namedParams", x -> x.namedParams(), isSequence( isShidDefineFunctionParam("b__0") )), has("freeVariables", x -> x.freeVariables(), containsExactly()), has("body", x -> x.body(), isShidBlock(isSequence( isShidPushString("hello"), isShidReturn() ))) ), isShidMethodStore(structType, "name") )); } }