git @ Cat's Eye Technologies Pophery / master src / minus-one.py
master

Tree @master (Download .tar.gz)

minus-one.py @masterraw · history · blame

# -*- coding: utf-8 -*-

"""
Semantics for the Pophery Programming Language, Version Minus One.

These are the original semantics I devised for Pophery, but ended up not
liking.  But I couldn't bear to throw them away either, so I stuffed them
into this (basically throw-away) language.

I don't think these semantics are Turing-complete.

Actually getting this to run will take a little hacking around with this file
and pophery.py, but should not be very hard.

"""


from pophery import Program


class Semantics(Program):
    def execute(self, instruction):
        """Apply the semantics of the given instruction to this Program.

        >>> p = Semantics("(^?)(?$)")
        >>> p.execute('0')
        >>> print str(p)
        (^?)0(?$)

        >>> p = Semantics("(^@)(@$)")
        >>> p.execute('@')
        >>> print str(p)
        (^@)@(@$)
        >>> p = Semantics("(^`@)Jim(`@$)(^Jim)?(Jim$)")
        >>> p.execute('@')
        >>> print str(p)
        (^`@)Jim(`@$)(^Jim)Jim(Jim$)

        >>> p = Semantics("(^?)(?$)(^@)0(@$)(^0)Seven(0$)")
        >>> p.execute('G')
        >>> print str(p)
        (^?)Seven(?$)(^@)0(@$)(^0)Seven(0$)

        >>> p = Semantics("(^?)Meerkat(?$)(^@)0(@$)(^0)Seven(0$)")
        >>> p.execute('P')
        >>> print str(p)
        (^?)Meerkat(?$)(^@)0(@$)(^0)Meerkat(0$)

        >>> p = Semantics("(^?)!(?$)(^@)0(@$)(^0)Fenesrate(0$)")
        >>> p.execute('A')
        >>> print str(p)
        (^?)!(?$)(^@)0(@$)(^0)!Fenesrate(0$)
        >>> p.execute('Z')
        >>> print str(p)
        (^?)!(?$)(^@)0(@$)(^0)!Fenesrate!(0$)

        >>> p = Semantics("(^@)0(@$)(^0)Seven(0$)")
        >>> p.execute('X')
        >>> print str(p)
        (^@)0(@$)(^0)(0$)

        >>> p = Semantics("(^@)0(@$)(^0)Licorice(0$)(^%)(%$)")
        >>> p.execute('C')
        >>> print str(p)
        (^@)0(@$)(^0)Licorice(0$)(^%)Licorice(%$)

        >>> p = Semantics("(^@)0(@$)(^0)Rock(0$)(^%)well(%$)")
        >>> p.execute('V')
        >>> print str(p)
        (^@)0(@$)(^0)Rockwell(0$)(^%)well(%$)

        >>> p = Semantics("(^@)0(@$)(^0)Rock(0$)(^%)well(%$)")
        >>> p.execute('V')
        >>> print str(p)
        (^@)0(@$)(^0)Rockwell(0$)(^%)well(%$)

        >>> p = Semantics("(^?)Hello, world!(?$)")
        >>> p.execute('O')
        Hello, world!
        >>> print str(p)
        (^?)Hello, world!(?$)

        >>> from StringIO import StringIO
        >>> p = Semantics("(^?)(?$)")
        >>> p.input = StringIO(chr(10).join(["Line.", "Line!", "LINE!"]))
        >>> p.execute('I')
        >>> print str(p)
        (^?)Line.(?$)
        >>> p.execute('I')
        >>> print str(p)
        (^?)Line!(?$)
        >>> p.execute('I')
        >>> print str(p)
        (^?)LINE!(?$)
        >>> p.execute('I')
        >>> print str(p)
        (^?)(?$)

        """
        if instruction >= '0' and instruction <= '9':
            self.update_slot(self.get_slot_name('?'), instruction)
        elif instruction == '@':
            self.update_slot(self.get_slot_name('@'), self.get_slot_name('@'))
        elif instruction == 'G':
            self.update_slot(self.get_slot_name('?'), self.read_slot_indirect(self.get_slot_name('@')))
        elif instruction == 'P':
            self.update_slot_indirect(self.get_slot_name('@'), self.read_slot('?'))
        elif instruction == 'A':
            value = self.read_slot('?') + self.read_slot_indirect(self.get_slot_name('@'))
            self.update_slot_indirect(self.get_slot_name('@'), value)
        elif instruction == 'Z':
            value = self.read_slot_indirect(self.get_slot_name('@')) + self.read_slot('?') 
            self.update_slot_indirect(self.get_slot_name('@'), value)
        elif instruction == 'X':
            self.update_slot_indirect(self.get_slot_name('@'), '')
        elif instruction == 'C':
            self.update_slot(self.get_slot_name('%'), self.read_slot_indirect(self.get_slot_name('@')))
        elif instruction == 'V':
            value = self.read_slot_indirect(self.get_slot_name('@')) + self.read_slot('%')
            self.update_slot_indirect(self.get_slot_name('@'), value)
        elif instruction == 'O':
            line = self.read_slot('?') + "\n"
            try:
                self.output.write(line)
            except UnicodeEncodeError:
                self.output.write(line.encode('ascii', 'xmlcharrefreplace'))
        elif instruction == 'I':
            text = self.input.readline()
            if text.endswith('\n'):
                text = text[:-1]
            self.update_slot(self.get_slot_name('?'), text)
        else:
            pass

    def step(self):
        """Execute one step of this Pophery program.

        >>> p = Semantics("(^?)Hello, world!(?$)(^!)O(!$)")
        >>> p.step()
        Hello, world!
        True
        >>> print str(p)
        (^?)Hello, world!(?$)O(^!)(!$)
        >>> p.step()
        False
        >>> print str(p)
        (^?)Hello, world!(?$)O(^!)(!$)

        """
        return super(Semantics, self).step()

    def run(self):
        """Execute this Pophery program and return only when it terminates.

        >>> p = Semantics("(^?)Hello, world!(?$)(^!)O(!$)OO")
        >>> p.run()
        Hello, world!
        Hello, world!
        Hello, world!

        >>> p = Semantics("(^0)Load Me(0$)(^?)(?$)(^@)(@$) (^!)0(!$)@PG")
        >>> p.run()
        >>> print str(p)
        (^0)Load Me(0$)(^?)Load Me(?$)(^@)0(@$) 0@PG(^!)(!$)

        >>> p = Semantics("(^0)Overwrite Me(0$)(^?)(?$)(^@)(@$) (^!)0(!$)@P1P")
        >>> p.run()
        >>> print str(p)
        (^0)1(0$)(^?)1(?$)(^@)0(@$) 0@P1P(^!)(!$)

        Accessing a slot with a longer name can be done with the help of a free slot:
        
        >>> p = Semantics("(^123)xyz(123$)(^0)(0$)(^?)(?$)(^@)(@$) (^!)0(!$)@P1P2Z3ZG@PG")
        >>> p.run()
        >>> print str(p)
        (^123)xyz(123$)(^0)123(0$)(^?)xyz(?$)(^@)123(@$) 0@P1P2Z3ZG@PG(^!)(!$)

        Let's use the clipboard to construct that name instead:

        >>> p = Semantics("(^123)xyz(123$)(^0)(0$)(^1)(1$)(^?)(?$)(^@)(@$)(^%)(%$) (^!) (!$)0@P1PC1@PV 0@P2PC1@PV 0@P3PC1@PV 1@PG@PG")
        >>> p.run()
        >>> print str(p)
        (^123)xyz(123$)(^0)3(0$)(^1)123(1$)(^?)xyz(?$)(^@)123(@$)(^%)3(%$)  0@P1PC1@PV 0@P2PC1@PV 0@P3PC1@PV 1@PG@PG(^!)(!$)

        To copy from one arbitrary slot to another, we can use the clipboard:

        >>> p = Semantics("(^0)Copy Me(0$)(^1)Overwrite Me(1$)(^?)(?$)(^@)(@$)(^%)(%$) (^!)0(!$)0@PC1@PXV")
        >>> p.run()
        >>> print str(p)
        (^0)Copy Me(0$)(^1)Copy Me(1$)(^?)1(?$)(^@)1(@$)(^%)Copy Me(%$) 00@PC1@PXV(^!)(!$)

        We can also use the clipboard "cut" command to halt the program, like so:

        >>> p = Semantics("(^0)!(0$)(^?)(?$)(^@)(@$) (^!)0(!$)0@PG@PXOOOOO")
        >>> p.run()
        >>> print str(p)
        (^0)!(0$)(^?)!(?$)(^@)!(@$) 00@PG@PO(^!)(!$)OOOO

        """
        return super(Semantics, self).run()