gabriele renzi wrote:

> Damn, now I have to write the COW one.. 
> givent that brainf**k and OOk! are already there maybe we should start
> a section on the wiki :)

Now I just *have* to post my Brainfuck interpreter where all 
instructions can dynamically be changed and new ones can be added 
without problems:

> begin
>   require 'simplecc'
> rescue LoadError
>   def Continuation.create(*args, &block)
>     cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
>     result ||= args
>     return *[cc, *result]
>   end
> end
> 
> class BrainfuckContext
>   def initialize(code = nil, instructions = {})
>     @data, @pointer, @jumps = Hash.new { 0 }, 0, []
>     @instructions = Instructions.merge(instructions)
>     execute code if code
>   end
> 
>   def execute(code)
>     code.split(//).each do |instruction|
>       instance_eval(&@instructions[instruction])
>     end
>   end
> 
>   def getc; STDIN.getc || 0; end
> 
>   Instructions = Hash.new { proc {} }.update({
>     '>' => proc { @pointer += 1 },
>     '<' => proc { @pointer -= 1 },
>     '+' => proc { @data[@pointer] += 1 },
>     '-' => proc { @data[@pointer] -= 1 },
>     '.' => proc { putc @data[@pointer] },
>     ',' => proc { @data[@pointer] = getc },
>     '[' => proc do
>       jump, jumped = Continuation.create(false)
>       @jumps << jump
>       unless jumped
>         @depth ||= 0
>         @depth += 1
>         # make all instructions but ']' noops
>         @old_instructions = @instructions.dup
>         new_instructions = {
>           '[' => proc { @depth += 1 },
>           ']' => proc do
>             @depth = [0, @depth - 1].max
>             if @depth == 0
>               # restore standard instruction table
>               @instructions.update(@old_instructions) if @old_instructions
>               @old_instructions = nil
>               
>               jump = @jumps.pop
>               jump.call(true) if jump and @data[@pointer] != 0
>             end
>           end
>         }
>         @instructions = @old_instructions.dup.clear.update(new_instructions)
>       end
>     end,
>     ']' => proc do
>       jump = @jumps.pop
>       jump.call(true) if jump and @data[@pointer] != 0
>     end,
>     '#' => proc do
>       data = @data.to_a.sort_by { |(key, value)|
>         key
>       }.map { |(key, value)|
>         "#{key} = #{value}"
>       }.join(", ")
>       puts "#{@pointer} @ [#{data}]"
>     end
>   })
> end
> 
> def bf(code)
>   BrainfuckContext.new(code)
> end