module RASEL
Constants
- ResultStruct
Public Class Methods
run(source, stdout = StringIO.new, stdin = STDIN)
click to toggle source
# File lib/rasel.rb, line 6 def self.run source, stdout = StringIO.new, stdin = STDIN stack = [] pop = ->{ stack.pop || 0 } error = Proc.new{ return RASEL::ResultStruct.new stdout, stack, 255 } lines = source.tap{ |_| raise ArgumentError.new "empty source" if _.empty? }.gsub(/ +$/,"").split(?\n) code = lines.map{ |_| _.ljust(lines.map(&:size).max).bytes } dx, dy = 1, 0 x, y = -1, 0 # debugging and profiling (currently not maintained) history = {} debug_history = ENV.key? "DEBUG_HISTORY" move = lambda do y = (y + dy) % code.size x = (x + dx) % code[y].size next unless debug_history && (code[y][x] == 32 || code[y][x][0] == 32) history[[x, y]] ||= 0 history[[x, y]] += 1 end time = Time.now thread = Thread.new do loop do unless Time.now < time + 1 time += 1 p history.sort_by(&:last).last(10) end sleep 0.1 end end if debug_history reverse = ->{ dy, dx = -dy, -dx } stringmode = false debug = ENV.key? "DEBUG" loop do move[] byte = code[y][x] char = byte.chr STDERR.puts [char, stringmode, (stack.last Integer ENV["DEBUG"] rescue stack)].inspect if debug next stack.push byte if stringmode && char != ?" return RASEL::ResultStruct.new stdout, stack, ( t = pop[] 1 != t.denominator || t < 0 || t > 255 ? 255 : t.to_i ) if char == ?@ case char when ?\s when ?0..?9 ; stack.push byte - 48 when ?A..?Z ; stack.push byte - 55 when ?" ; stringmode ^= true when ?# ; move[] when ?: ; stack.concat [pop[]] * 2 when ?- ; stack.push -(pop[] - pop[]) when ?/ ; b, a = pop[], pop[]; stack.push b.zero? ? 0 : Rational(a) / b when ?% ; b, a = pop[], pop[]; stack.push b.zero? ? 0 : Rational(a) % b when ?v ; dx, dy = 0, 1 when ?> ; dx, dy = 1, 0 when ?^ ; dx, dy = 0, -1 when ?< ; dx, dy = -1, 0 when ?? ; move[] if pop[] > 0 when ?\\ t = pop[] error.call if 1 != t.denominator stack.unshift 0 until stack.size > t stack[-t-1], stack[-1] = stack[-1], stack[-t-1] unless 0 > t when ?. ; stdout.print "#{_ = pop[]; 1 != _.denominator ? _.to_f : _.to_i} " when ?, ; stdout.print "#{_ = pop[]; 1 != _.denominator ? error.call : _ < 0 || _ > 255 ? error.call : _.to_i.chr}" when ?~ ; if _ = stdin.getbyte then stack.push _; move[] end when ?& getc = ->{ stdin.getc or throw nil } catch nil do nil until (?0..?9).include? c = getc[] while (?0..?9).include? cc = stdin.getc ; c << cc end stdin.ungetbyte cc if cc stack.push c.to_i move[] end when ?j t = pop[] error.call if 1 != t.denominator y = (y + dy * t.to_i) % code.size x = (x + dx * t.to_i) % code[y].size else ; error.call end end end
run_annotated(source, stdout = StringIO.new, stdin = STDIN)
click to toggle source
# File lib/rasel.rb, line 104 def self.run_annotated source, stdout = StringIO.new, stdin = STDIN stack = [] pop = ->{ stack.pop || 0 } error = Proc.new{ return ResultStruct.new stdout, stack, 255 } code = Array.new(source.map{|y,|y}.max+1){ Array.new(source.map{|_,x,|x}.max+1){ " ".ord } } source.each{ |y, x, c, a| code[y][x] = [c.ord, a] unless c.empty? } stdout.instance_eval do pos = self.pos old_puts = method :puts prev = nil define_singleton_method :puts do |str, reason| next if prev == dump = JSON.dump([reason, str]) old_puts.call prev = dump if ENV.fetch("IDE_LIMIT_PRINTED", "500000").to_i < stdout.pos - pos old_puts.call JSON.dump [:abort, "printed size"] error.call end end define_singleton_method :print do |str| puts str, :print end end dx, dy = 1, 0 x, y = -1, 0 move = lambda do y = (y + dy) % code.size x = (x + dx) % code[y].size end time = Time.now reverse = ->{ dy, dx = -dy, -dx } stringmode = false loop do if 1 < Time.now - time stdout.puts "timeout", :abort error.call end stdout.puts stack.map{ |_| _.respond_to?(:annotation) && _.annotation ? [_, _.annotation] : _ }, :loop move[] byte, annotation = code[y][x] char = byte.chr next stack.push StackItem.new byte, annotation if stringmode && char != ?" return ResultStruct.new stdout, stack, ( t = pop[] 1 != t.denominator || t < 0 || t > 255 ? 255 : t.to_i ) if char == ?@ case char when ?\s when ?0..?9 ; stack.push StackItem.new byte - 48, annotation when ?A..?Z ; stack.push StackItem.new byte - 55, annotation when ?" ; stringmode ^= true when ?# ; move[] when ?: ; popped = pop[]; stack.push popped; stack.push StackItem.new popped, annotation when ?- ; stack.push StackItem.new -(pop[] - pop[]), annotation when ?/ ; b, a = pop[], pop[]; stack.push StackItem.new b.zero? ? 0 : Rational(a) / b, annotation when ?% ; b, a = pop[], pop[]; stack.push StackItem.new b.zero? ? 0 : Rational(a) % b, annotation when ?v ; dx, dy = 0, 1 when ?> ; dx, dy = 1, 0 when ?^ ; dx, dy = 0, -1 when ?< ; dx, dy = -1, 0 when ?? ; move[] if pop[] > 0 when ?\\ t = pop[] error.call if 1 != t.denominator stack.unshift 0 until stack.size > t stack[-t-1], stack[-1] = StackItem.new(stack[-1], annotation), stack[-t-1] unless 0 > t # TODO: annotate prints when ?. ; stdout.print "#{_ = pop[]; 1 != _.denominator ? _.to_f : _.to_i} " when ?, ; stdout.print "#{_ = pop[]; 1 != _.denominator ? error.call : _ < 0 || _ > 255 ? error.call : _.to_i.chr}" when ?~ ; if _ = stdin.getbyte then stack.push StackItem.new _, annotation; move[] end when ?& getc = ->{ stdin.getc or throw nil } catch nil do nil until (?0..?9).include? c = getc[] while (?0..?9).include? cc = stdin.getc ; c << cc end stdin.ungetbyte cc if cc stack.push StackItem.new c.to_i, annotation move[] end when ?j t = pop[] error.call if 1 != t.denominator y = (y + dy * t.to_i) % code.size x = (x + dx * t.to_i) % code[y].size else ; error.call end end end
write_pretty_json(where, what)
click to toggle source
# File lib/rasel.rb, line 200 def self.write_pretty_json where, what File.write where, "[\n " + ( what.map(&JSON.method(:dump)).join ",\n " ) + "\n]\n" end