<moya xmlns:let="http://moyaproject.com/let">

    <macro docname="bf">
        <let memory="[0]*30000" cp="0" ip="0" in="0"/>
        <list dst="output"/>

        <repeat>

            <let c="program[ip]"/>
            <break if="missing:c"/>

            <switch on="c">
                <case>&gt;</case>
                <let cp="(cp + 1) % len:memory"/>

                <case>&lt;</case>
                <let cp="(cp - 1) % len:memory"/>

                <case>+</case>
                <set-item src="memory" index="cp" value="memory[cp] + 1" />

                <case>-</case>
                <set-item src="memory" index="cp" value="memory[cp] - 1" />

                <case>.</case>
                <append src="output" value="chr:memory[cp]" />

                <case>,</case>
                <let v="input[in] or 0" in="in+1"/>
                <set-item src="memory" index="cp" value="v"/>

                <case>[</case>
                <if test="memory[cp] == 0">
                    <let braces="1"/>
                    <while test="braces">
                        <let ip="ip + 1" c="program[ip]"/>
                        <switch on="c">
                            <case>[</case><let braces="braces+1"/>
                            <case>]</case><let braces="braces-1"/>
                        </switch>
                    </while>
                </if>

                <case>]</case>
                <let braces="1"/>
                <while test="braces">
                    <let ip="ip - 1" c="program[ip]"/>
                    <switch on="c">
                        <case>[</case><let braces="braces-1"/>
                        <case>]</case><let braces="braces+1"/>
                    </switch>
                </while>
                <dec dst="ip"/>
            </switch>

            <inc dst="ip"/>

        </repeat>
        <return value="join:output"/>
    </macro>

    <macro docname="main">
        <!-- BF programs are tricky to quote in XML due to their use of > and < -->
        <str dst="example"><![CDATA[++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.]]></str>
        <if test="not program">
            <echo>A B*******k interpreter (http://en.wikipedia.org/wiki/Brainfuck)</echo>
            <echo>Run with --let program="BF program"</echo>
            <echo>e.g.</echo>
            <echo>  moya run bf.xml --let program="${example}"</echo>
            <echo>Set input with --let input="my input"</echo>
            <exit/>
        </if>

        <call macro="bf" let:program="program" let:input="input" dst="output"/>
        <echo>${output}</echo>
    </macro>

</moya>