package org.shedlang.compiler.shid; import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.typed.Typed; import java.util.List; import static org.shedlang.compiler.shid.instructions.ShidMatchers.*; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.isSequence; public class ShidCodeGenWhileTests { @Test public void whileIsCompiledToLoop() { var node = Typed.while_( Typed.reference("c"), Typed.block(List.of( Typed.expressionStatement(Typed.intLiteral(42)) )) ); var context = ShidCodeGen.Context.EMPTY .addShedVal("c"); var result = ShidCodeGen.compileFunctionStatement(node, context); assertThat(result.instructions(), isSequence( isShidLoop( isShidBlock(isSequence( isShidLocalLoad("c__0"), isShidIf( isShidBlock(isSequence()), isShidBlock(isSequence( isShidLoopBreak() )) ), isShidBlock(isSequence( isShidPushInt(42), isShidDiscard() )), isShidLoopContinue() )) ) )); } @Test public void whenBodyYieldsValueThenValueIsDiscarded() { // In principle, the type checker should prevent the body from yielding // a value, but we check we handle this case anyway. var node = Typed.while_( Typed.reference("c"), Typed.block(List.of( Typed.blockReturn(Typed.intLiteral(42)) )) ); var context = ShidCodeGen.Context.EMPTY .addShedVal("c"); var result = ShidCodeGen.compileFunctionStatement(node, context); assertThat(result.instructions(), isSequence( isShidLoop( isShidBlock(isSequence( isShidLocalLoad("c__0"), isShidIf( isShidBlock(isSequence()), isShidBlock(isSequence( isShidLoopBreak() )) ), isShidBlock(isSequence( isShidPushInt(42), isShidDiscard() )), isShidLoopContinue() )) ) )); } }