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.

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

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     \--/ | ^ \-/