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