Ora

Ora is a (semi)reversible language created by User:zeotrope, it is influenced heavily by 2D-Reverse.
==Instructions==
* $ : Start position of program, moving right. u, d, l and r may also be used instead of $ to specify both a start position and direction.
* @ : Ends program.
* \ : Right reflector.
* / : Left reflector.
* - : Vertical reflector, does nothing if encountered when moving horizontally.
* | : Horizontal reflector, does nothing if encountered when moving vertically.
* C : Clockwise Rotate.
* A : Anti-clockwise Rotate.
* X : If current buffer element is non zero acts like a right reflector, otherwise it acts like a left reflector.
* x : If current buffer element is non zero acts like a left reflector, otherwise it acts like a right reflector.
* u : Set pointer direction to up.
* d : Set pointer direction to down.
* l : Set pointer direction to left.
* r : Set pointer direction to right.
==Operation==
The program pointer starts travelling at the $ symbol, moving towards the right. The starting direction may be altered by
using the u, d, l and r instructions as a start instruction instead of $.
If the program encounters a space or a "." as it moves it manipulates an infinite one dimensional buffer based on the direction it is travelling in the following manner:
* If the program is moving right the current buffer element is incremented.
* If the program is moving left the current buffer element is decremented.
* If the program is moving up the next (right) buffer element is set as the current element.
* If the program is moving up the previous (left) buffer element is set as the current element.
If a program move is performed without encountering a "." or a space, none of the above is executed.
==Examples==
===Cell Clear===
Decrement current buffer element until it is zero.
 /.A
 $....r-x
 @
Brainfuck equivalent:
 ++++[-]
===Rewind===
Move left along buffer until a zero element is encountered, increment it.
 /.\/.@
 . rX
 /./ |.
 . \/
 /./ 
 .
 $-/
Brainfuck equivalent:
 >+>+>+[<]>
===Clear Previous Cell===
Decrement current buffer cell and all previous buffer cells until zero, stop at first zero encountered.
 /..\
 . |/.A
 r../ \r-x
 | .
 \-x@
===Add===
Add 3 and 4.
 /...\/-----\
 . .|@ |
 $..../ \rX /.\|
 /./ . .|
 \---/ \/
==Interpreter==
 class TwoD
 attr_reader :prog, :len, :current, :bf
 attr_accessor :pos, :direction, :bpos, :buffer
 def initialize(string)
 @prog = string.split("\n").collect {|x| x.split("")}
 @len = @prog.length
 @direction = :right
 @bpos = 0
 @buffer = [0]
 @bf = []
 locate_start
 read_current
 end
 
 def gen_bf(i)
 @bf << i
 end
 
 def print_bf
 puts ""
 @bf.each {|x| print x}
 puts ""
 end
 
 def locate_start
 @pos = [0, 0]
 (0..@len-1).each do |i|
 case
 when @prog[i].include?("$") then
 @pos = [i, @prog[i].index("$")]
 when @prog[i].include?("u") then
 @pos = [i, @prog[i].index("u")]
 @direction = :up
 when @prog[i].include?("d") then
 @pos = [i, @prog[i].index("d")]
 @direction = :down
 when @prog[i].include?("l") then
 @pos = [i, @prog[i].index("l")]
 @direction = :left
 when @prog[i].include?("r") then
 @pos = [i, @prog[i].index("r")]
 @direction = :right
 end
 end
 end
 
 def read_current
 @current = @prog[@pos[0]][@pos[1]]
 end
 
 def buffer_right
 if (@bpos += 1) >= @buffer.length
 @buffer << 0
 end
 gen_bf(">")
 end
 
 def buffer_left
 if (@bpos -= 1) < 0
 @buffer = [0]+@buffer
 end
 gen_bf("<")
 end
 
 def step
 case @direction
 when :up then @pos[0] -= 1
 when :down then @pos[0] += 1
 when :right then @pos[1] += 1
 when :left then @pos[1] -= 1
 end
 read_current
 eval
 end
 
 def eval_spaces
 case @direction
 when :up then buffer_right
 when :down then buffer_left
 when :left then @buffer[@bpos] -= 1; gen_bf("-")
 when :right then @buffer[@bpos] += 1; gen_bf("+")
 end
 end
 
 def eval
 case @current
 when "/" then
 case @direction
 when :up then @direction = :right
 when :down then @direction = :left
 when :left then @direction = :down
 when :right then @direction = :up
 end
 when "\\" then
 case @direction
 when :up then @direction = :left
 when :down then @direction = :right
 when :left then @direction = :up
 when :right then @direction = :down
 end
 when "C" then
 case @direction
 when :up then @direction = :right
 when :down then @direction = :left
 when :left then @direction = :up
 when :right then @direction = :down
 end
 when "A" then
 case @direction
 when :up then @direction = :left
 when :down then @direction = :right
 when :left then @direction = :down
 when :right then @direction = :up
 end
 when "X" then
 if @buffer[@bpos] != 0
 @current = "\\"
 else
 @current = "/"
 end
 eval
 when "x" then
 if @buffer[@bpos] != 0
 @current = "/"
 else
 @current = "\\"
 end
 eval
 when "u" then @direction = :up
 when "d" then @direction = :down
 when "r" then @direction = :right
 when "l" then @direction = :left
 when "|" then 
 case @direction
 when :left then @direction = :right
 when :right then @direction = :left
 end
 when "-" then
 case @direction
 when :up then @direction = :down
 when :down then @direction = :up
 end
 when ".", " " then eval_spaces
 when "@" then disp; print_bf; exit(1)
 end
 end
 
 def disp
 puts "\tbuffer #{$test.buffer}\tpos #{$test.pos}\tcurrent #{$test.current}\tdirection #{$test.direction}"
 end
 
 def run
 disp
 step
 end
 
 def print_prog
 (0..@len-1).each do |i|
 (0..@prog[i].length).each do |j|
 if ([i, j] == @pos)
 print "\033[44;37;5m#{@current} \033[0m"
 else
 print @prog[i][j]
 end
 end
 print "\n"
 end
 STDOUT.flush
 sleep(0.3)
 system("clear")
 end
 end
 
 $test = TwoD.new(File.read(ARGV[0]))
 $steps = ARGV[1]
 system("clear")
 
 if $steps.nil?
 loop do
 $test.print_prog
 $test.disp
 $test.step
 end
 else
 $steps.to_i.times do |x|
 $test.print_prog
 $test.disp
 $test.step
 end
 end
 ruby 2d.rb <file> <steps>
==Ideas==
* Function definition using <,>, ^ and v. Code in between these symbols is stored as a named function, these symbols may also be used as entry point specifiers , note: function's 2d representation must be stored. If a function omits certain entry points, it will not be called if it is executed using that entry point. 2 entry points must be specified at a minimum.
Defines a function s which can be executed from the left or from the bottom:
 >s]...\
 .
 ^
Definition of the built-in clockwise operator C.
 $\
 v
 C @
 ] v
 />/<->C]\]C\
 | ] ^ |
 | C \--/
 | ^
 \-/
Category:Languages
Category:Reversible computing
Category:2010
Category:Two-dimensional languages