Skip to content

Instantly share code, notes, and snippets.

@yaskovdev
Last active December 6, 2024 00:15
Show Gist options
  • Save yaskovdev/71010ede2d070ed88c11334160fedc88 to your computer and use it in GitHub Desktop.
Save yaskovdev/71010ede2d070ed88c11334160fedc88 to your computer and use it in GitHub Desktop.
Push Implementation of a 5-Register Universal Register Machine (URM) Interpreter

See this page, "URM is BF-complete" for more details about the Universal Register Machine.

Psh is used as the Push interpreter.

The interpreter accepts an URM program encoded as follows:

URM Symbol Encoding
. 0
a -1
s -2
( -3
) -4
1 1
2 2
3 3
4 4
5 5

The first line represents the registers, and the second line contains the encoded URM program. The first register is not addressable but is included to maintain 0-based indexing.

The memory is organized as follows (purpose and inclusive ranges): [REGISTERS: 0–5][CODE: 6–59][VARIABLES: 60–61].

The code of the URM interpreter in Push with a sample URM program that multiplies register 3 to register 2:

(
    0 0 6 3 0 0
    -3 -1 4 -1 5 -2 2 -4 2 -3 -3 -1 2 -2 4 -4 4 -2 3 -3 -1 1 -1 4 -2 5 -4 5 -3 -1 5 -2 1 -4 1 -4 3 0

    integer.stackdepth 62 integer.swap integer.-
    exec.do*times 0
    integer.stackdepth exec.do*count
    (
        integer.yank
    )

    exec.y
    (
        60 integer.yankdup
        (6 integer.+) integer.yankdup

        integer.dup
        (0 integer.=) exec.if
        (
            integer.pop
            exec.flush
        ) ()

        integer.dup
        (-1 integer.=) exec.if
        (
            (1 60 integer.+) integer.yank
            1 integer.+
            (1 60 integer.+) integer.shove

            1 60 integer.+ integer.yankdup
            1 (6 integer.+) integer.+ integer.yankdup
            integer.dup
            (2 integer.+) integer.yank
            1 integer.+
            integer.swap
            (1 integer.+) integer.shove
        ) ()

        integer.dup
        (-2 integer.=) exec.if
        (
            (1 60 integer.+) integer.yank
            1 integer.+
            (1 60 integer.+) integer.shove

            1 60 integer.+ integer.yankdup
            1 (6 integer.+) integer.+ integer.yankdup
            integer.dup
            (2 integer.+) integer.yank
            -1 integer.+
            integer.swap
            (1 integer.+) integer.shove
        ) ()

        integer.dup
        (-3 integer.=) exec.if
        (
            (1 61 integer.+) integer.yank
            1 integer.+
            (1 61 integer.+) integer.shove

            exec.y
            (
                (1 61 integer.+) integer.yankdup
                0 integer.>

                exec.if
                (
                    (1 60 integer.+) integer.yank
                    1 integer.+
                    (1 60 integer.+) integer.shove

                    1 60 integer.+ integer.yankdup
                    1 (6 integer.+) integer.+ integer.yankdup

                    integer.dup
                    (-3 integer.=) exec.if
                    (
                        (2 61 integer.+) integer.yank
                        1 integer.+
                        (2 61 integer.+) integer.shove
                    ) ()

                    integer.dup
                    (-4 integer.=) exec.if
                    (
                        (2 61 integer.+) integer.yank
                        -1 integer.+
                        (2 61 integer.+) integer.shove
                    ) ()

                    integer.pop
                ) exec.pop
            )

            (1 60 integer.+) integer.yank
            -1 integer.+
            (1 60 integer.+) integer.shove
        ) ()

        integer.dup
        (-4 integer.=) exec.if
        (
            1 60 integer.+ integer.yankdup
            2 (6 integer.+) integer.+ integer.yankdup
            (1 integer.+) integer.yankdup

            (0 integer.>) exec.if
            (
                (1 61 integer.+) integer.yank
                1 integer.+
                (1 61 integer.+) integer.shove

                exec.y
                (
                    (1 61 integer.+) integer.yankdup
                    0 integer.>

                    exec.if
                    (
                        (1 60 integer.+) integer.yank
                        -1 integer.+
                        (1 60 integer.+) integer.shove

                        1 60 integer.+ integer.yankdup
                        1 (6 integer.+) integer.+ integer.yankdup

                        integer.dup
                        (-4 integer.=) exec.if
                        (
                            (2 61 integer.+) integer.yank
                            1 integer.+
                            (2 61 integer.+) integer.shove
                        ) ()

                        integer.dup
                        (-3 integer.=) exec.if
                        (
                            (2 61 integer.+) integer.yank
                            -1 integer.+
                            (2 61 integer.+) integer.shove
                        ) ()

                        integer.pop
                    ) exec.pop
                )
            )
            (
                (1 60 integer.+) integer.yank
                1 integer.+
                (1 60 integer.+) integer.shove
            )
        ) ()

        integer.pop

        60 integer.yank
        1 integer.+
        60 integer.shove
    )
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment