Commits

catseye  committed 7db0714

Initial import of Jolverine 1.0 sources.

  • Participants

Comments (0)

Files changed (8)

File README.markdown

+Jolverine
+=========
+
+Language version 1.0
+
+The Jolverine language was devised as a conscious attempt to expand the
+genre of turning tarpit by adding the feature of modifying the instruction
+wheel during execution.  It is not dissimilar to Wunnel, and was influenced
+slightly by Half-Broken Car in Heavy Traffic.
+
+The name is either a portmanteau of "jolly wolverine" (where "jolly" is a
+euphemism for "drunk",) which is an attempt to capture, in a noun phrase, the
+language's vicious, erratic nature.
+
+Program Structure
+-----------------
+
+A Jolverine program consists of a two-dimensional grid of symbols.  An
+instruction pointer (IP) traverses the grid, starting in the upper-left
+corner (x=0, y=0) travelling right (dx=1, dy=0).  dx and dy have only
+three possible values, -1, 0, and 1, like values on the tape (see below.)
+
+Execution
+---------
+
+On each tick, if the symbol under the IP is a `*`, the current instruction on
+the instruction wheel is executed.  The instruction wheel is then advanced to
+the next instruction, regardless of what the symbols under the IP contains.
+(All symbols that are not `*` have the same meaning, that is to say, no
+meaning besides taking up space.)  The IP is then advanced to the next
+position in the playfield, and the next tick begins.  Execution halts when
+the IP travels beyond the extent of the playfield (i.e. when it can be proved
+that, in its direction of travel, it will never again hit a `*`.)
+
+Storage
+-------
+
+There is an unbounded tape, with a single head which can be moved left
+and right.  Each cell on the tape may contain one of the three values -1, 0,
+or 1.  Initially, all tape cells contain 0.  Addition and subtraction of these
+values is always "mod 3 - 1": incrementing 1 yields -1 and decrementing -1
+yields 1.
+
+Instruction Wheel
+-----------------
+
+The instruction wheel contains seven instructions.  Initially, the wheel looks
+like this:
+
+    left <--
+    right
+    rot
+    adddx
+    adddy
+    input
+    output
+
+The arrow indicates the current instruction on the wheel.  Each time the
+wheel is advanced, the arrow moves down one row, wrapping around back
+to the top once it advances past the bottom of the wheel.
+
+Each time an instruction is executed from the wheel, it is removed from the
+wheel and re-inserted at a different position.  The first time this happens, it
+is re-inserted at the top of the wheel; the second time, it is re-inserted at
+the bottom; the third time, at the top again; the fourth time, at the bottom
+again; and so forth.
+
+Instructions
+------------
+
+*   `left`: moves the tape head left one tape cell.
+*   `right`: moves the tape head right one tape cell.
+*   `rot`: increments the current tape cell.
+*   `adddx`: adds the contents of the current tape cell to the IP's dx.
+*   `adddy`: adds the contents of the current tape cell to the IP's dy.
+*   `input`: inputs a single bit (I/O is bitwise, and implementation-defined.)
+*   `output`: if the current tape cell is 0, output a 0; if the current tape
+    cell is 1, output a 1; otherwise RESERVED for future expansion.
+
+Notes
+-----
+
+It is entirely possible for `*` to execute `adddx` or `adddy` with the result
+of both dx and dy being zero.  In this case, execution does not halt, but
+the same `*` will be executed again, and again, until dx or dy changes.
+
+Computational Class
+-------------------
+
+Jolverine may or may not be Turing-complete.  If it is not, it is not because
+it has insufficient storage, or no way to execute an instruction it has
+previously executed; it will be because there is no way to predictably
+execute the same series of instructions as was previously executed.
+
+Discussion
+----------
+
+I have yet to write a proper loop in Jolverine.  I have only attempted to
+write an infinite loop, executing `adddx` and `adddy` alternately after
+`rot`ing a cell on the tape.  After a few iterations, you can guarantee
+that `adddx` is at the top of the wheel, and `adddy` at the bottom, so you
+can choose to execute the next one, as appropriate, and it will not change
+the position of these instructions on the wheel (because they're already at
+the top and bottom.)  However, I suspect even this technique really requires
+some number theory to do effectively -- probably finding the LCM of 7 (the
+number of instructions on the wheel) and a couple of other numbers (the
+amount you can change the x and y positions on each spin around the
+playfield.)
+
+Happy wheel-mangling! 
+Chris Pressey 
+September 11, 2012 
+Montréal, Québec
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>

File eg/invert-one-bit.jol

+--*-*
+     \
+      \
+       \           *
+        \         /
+         \       /
+          \     /
+           *   /
+            \ /
+             *-*---*

File eg/loop-attempt-1.jol

+--*----------------------*
+                          \
+      *      *------------*\      
+             |             \\    
+             |              \\  
+             |               \\
+             |                \*
+             |                /\
+             |               /  \
+             |              /    \
+             |             /      *
+             |            /      /
+             |           /      /
+             |          /      /
+             |         /      /
+             |        /      /   
+             |       /      /     
+             |      /      /      
+             |     /      /      
+             |    /      /      
+      |      |   /      /
+      |      |  /      /
+      *      * /      /
+       \      *      /
+        \           /
+         \         /
+          \       /
+           \     /
+            \   /
+             \ /
+              *

File eg/loop-attempt-2.jol

+--*----------------------*
+                          \
+             *------------*\      
+             |             \\    
+             |              \\  
+             |               \\
+             |                \*
+             |                /\
+             |               /  \
+             |              /    *
+             |             /      
+             |            /      
+             |           /      
+             |          /      
+             |         /      
+             |        /         
+             |       /           
+             |      /            
+             |     /            
+             |    /            
+             |   /      
+             |  /      
+             * /      
+              *      
+                    
+                   
+                  
+                 
+                
+               
+              

File eg/loop-attempt-3.jol

+--*----------------------*
+                          \
+             *------------*\      
+        *------------*     \\    
+        |*---------*  \     \\ 
+    *   /    |      \  \     \\
+   /   /|    |       \  \     \*
+  /   * |    |        \  \    /\ 
+ *    | |    |         \  \  /  \ 
+ |    | |    |          *  \/    \ 
+ |    | |    |         /   /\     * 
+ |    | |    |        /   /  *   /   
+ |    | |    |       /   /  /   /    
+ |    * |    |      /   /  /   /
+ *    | |    |     /   /  /   /
+ |    | |    |    /   /  /   /   
+ |    | |    |   /   /  /   /     
+ |    | |    |  /   /  /   /      
+ |    | |    | /   /  /   /      
+ |    | |    |/   /  /   /      
+ |    * |    |   /  /   /
+ *    | |   /|  /  /   /
+ |    * |  / * /  /   /
+ *     \* /   *  /   /
+  \     \*      /   /
+   \     \     /   /
+    \     \   /   /
+     \     \ /   /
+      \     X   /
+       \   / \ /
+        \ /   *
+         *    

File eg/loop-attempt-4.jol

+--*----------------------*
+                          \
+                           \      
+                            \    
+                *--*         \ 
+               /    \         \
+              /      \         *
+             *        \       /  
+             |         \     /    
+             |          *   /      
+             |         /   /       
+             |        /   /      
+             |       /   /          
+             *      /   /      
+             |     /   /      
+             |    /   /         
+             |   /   /           
+             |  /   /            
+             | *   /            
+             | |  /            
+             * | /      
+             |  /      
+             * /      
+              *      
+                    
+                  
+                 
+                
+               
+              
+              
+              

File src/jolverine.py

+# Reference interpreter for Jolverine 1.0
+# Sept 12, 2012, Chris Pressey, Cat's Eye Technologies
+# This program is in the public domain -- see the file UNLICENSE.
+
+import sys
+
+class Program(object):
+    def __init__(self, program, debug=False):
+        self.wheel = [
+            'left',
+            'right',
+            'rot',
+            'adddx',
+            'adddy',
+            'input',
+            'output',
+        ]
+        self.index = 0
+        self.head = 0
+        self.tape = {}
+        self.playfield = {}
+        self.insertpos = 'bottom'
+        self._debug = debug
+        y = 0
+        self.maxx = 0
+        for line in file:
+            line = line.rstrip('\r\n')
+            x = 0
+            while x < len(line):
+                self.playfield[(x, y)] = line[x]
+                x += 1
+            if x > self.maxx:
+                self.maxx = x
+            y += 1
+        self.maxy = y
+        self.x = 0
+        self.y = 0
+        self.dx = 1
+        self.dy = 0
+
+    ### helpers ###
+    
+    def limit(self, x):
+        if x == 2:
+            return -1
+        if x == -2:
+            return 1
+        return x
+
+    ### instructions ###
+    
+    def left(self):
+        self.head -= 1
+
+    def right(self):
+        self.head += 1
+
+    def rot(self):
+        val = self.tape.get(self.head, 0)
+        val += 1
+        val = self.limit(val)
+        self.tape[self.head] = val
+
+    def adddx(self):
+        self.dx += self.tape.get(self.head, 0)
+        self.dx = self.limit(self.dx)
+
+    def adddy(self):
+        self.dy += self.tape.get(self.head, 0)
+        self.dy = self.limit(self.dy)
+
+    def input(self):
+        c = sys.stdin.read(1)
+        if c == '0':
+            pass
+        elif c == '1':
+            self.rot()
+        elif c in (' ', '\n', '\r', '\t'):
+            pass
+        else:
+            raise ValueError("Illegal binary input character '%s'" % c)
+
+    def output(self):
+        val = self.tape.get(self.head, 0)
+        if val == 1:
+            c = sys.stdout.write('1')
+            sys.stdout.flush()
+        elif val == 0:
+            c = sys.stdout.write('0')
+            sys.stdout.flush()
+        else:
+            raise ValueError("Illegal binary output value '%d'" % val)
+
+    ### execution ###
+
+    def cycle(self):
+        self.index += 1
+        self.index %= len(self.wheel)
+
+    def execute(self):
+        name = self.wheel[self.index]
+        self.debug("*                    EXECUTING %s @ (%d,%d)" % (name, self.x, self.y))
+        command = getattr(self, name)
+        command()
+        self.wheel.pop(self.index)
+        if self.insertpos == 'bottom':
+            self.wheel.insert(0, name)
+            self.insertpos = 'top'
+        else:
+            self.wheel.append(name)
+            self.insertpos = 'bottom'
+
+    def run(self):
+        while True:
+            instr = self.playfield.get((self.x, self.y), ' ')
+            if instr == '*':
+                self.execute()
+            self.cycle()
+            self.x += self.dx
+            self.y += self.dy
+            self.dump()
+            if (self.x < 0 or self.y < 0 or
+                self.x > self.maxx or self.y > self.maxy):
+                break
+
+    ### debugging ###
+    
+    def dump(self):
+        if not self._debug:
+            return
+        print "------------"
+        print "x=%d,y=%d,dx=%d,dy=%d" % (self.x, self.y, self.dx, self.dy)
+        print "head: %d cell: %d" % (self.head, self.tape.get(self.head, 0))
+        print "Next reinsert: %s" % self.insertpos
+        print "Wheel:"
+        print "------------"
+        i = 0
+        for x in self.wheel:
+            arrow = "   "
+            if i == self.index:
+                arrow = "-->"
+            print "%s %d. %s" % (arrow, i, x)
+            i += 1
+        print "------------"
+
+
+    def debug(self, msg):
+        if self._debug:
+            print msg
+
+if __name__ == '__main__':
+    debug = False
+    fnai = 1
+    if sys.argv[1] == '-d':
+        debug = True
+        fnai = 2
+    with open(sys.argv[fnai]) as file:
+        p = Program(file, debug=debug)
+    p.dump()
+    p.run()