Class: RpRb::DC
- Inherits:
-
Object
- Object
- RpRb::DC
- Defined in:
- lib/rprb.rb
Instance Method Summary collapse
- #eval(tokens) ⇒ Object
- #execute(fn) ⇒ Object
-
#initialize ⇒ DC
constructor
A new instance of DC.
- #parse_code(stream) ⇒ Object
- #read(val) ⇒ Object
- #stack ⇒ Object
- #without_comments(string) ⇒ Object
Constructor Details
#initialize ⇒ DC
Returns a new instance of DC.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/rprb.rb', line 36 def initialize @reader = Reader.new @stack = [] @registers = { :eval => proc { |x| eval x }, :read => proc { |x| read x }, :p => proc { || puts "___" puts @stack.collect_with_index { |entry, i| "%3d: %s" % [i, entry.inspect] }.reverse.join("\n") puts "---" :noval }, :pick => proc { |n| @stack[n] }, :del => proc { |n| @stack.slice!(n); :noval }, :sto => proc { |val, sym| @registers[sym] = val; :noval }, :rcl => proc { |sym| @registers[sym] }, :if => proc { |den, elz, test| if test; den; else; elz; end }, :len => proc { || @stack.length }, :push => proc { |array, elem| array.push elem; array }, :while => proc { |expr, cond| loop { eval(cond); break unless @stack.shift; eval(expr) }; :noval }, :evaln => proc { |expr, n| n.times { eval(expr) }; :noval }, :loop => proc { |expr, times| times.times { |i| @stack.unshift(i); eval(expr) }; :noval }, :each => proc { |enumerable, expr| enumerable.each { |elem| @stack.unshift(elem); eval(expr) }; :noval }, :array => proc { |length| @stack.slice!(0, length).reverse }, :regs => proc { || @registers.keys }, } [ read('{ Array.new } :"[]" sto'), read('0 array :control sto'), read('{ false true 2 pick if 1 del } :not sto'), read('{ :control rcl swap unshift :control sto } :save sto'), read('{ :control rcl 0 slice! } :restore sto'), read('{ 1 pick 2 del } :swap sto'), read('{ 0 del } :drop sto'), read('{ 0 pick } :dup sto'), read('{ {drop} swap evaln } :dropn sto'), read('{ 2 dropn } :drop2 sto'), read('{ 2 dupn } :dup2 sto'), read('{ len dropn } :clr sto'), read('{ rcl eval } :exe sto'), read('{ swap rcl swap evaln } :exen sto'), read('{ 1 - } :dec sto'), read('{ 1 + } :inc sto'), read('{ -1 * } :neg sto'), read('{ 1.0 swap / } :inv sto'), read('{ restore dup save } :peek sto'), read('{ restore drop save } :poke sto'), read('{ save {peek 1 - pick} peek evaln restore drop } :dupn sto'), read('0 array :nop sto'), read('{ swap dup length save swap each restore array } :map sto'), read('{ File swap open save peek readlines restore close drop } :slurp sto'), read('{ slurp {chomp} map {read} map {eval} each } :load sto'), read('{ inc dup pick swap del } :take sto'), read('{ len {+} swap dec evaln } :sum sto'), ].each { |stream| eval(stream) } end |
Instance Method Details
#eval(tokens) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/rprb.rb', line 117 def eval(tokens) #puts "Eval-ing #{tokens.inspect}" tokens.each { |token| #puts "processing token #{token.inspect}..." result = trythese( *[ proc { execute(token.intern) }, proc { parse_code(token) }, proc { Kernel.eval(token) }, proc { puts("Error, nothing left to do"); :noval }, ] ) unless result == :noval @stack.unshift result end } :noval end |
#execute(fn) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/rprb.rb', line 146 def execute(fn) # check if /fn/ names a register if @registers.include? fn case @registers[fn] when Proc, Method values = @stack.slice!(0, @registers[fn].arity).reverse return @registers[fn].call(*values) else return eval(@registers[fn]) end end # check if /fn/ is a valid function call for an item on the stack @stack.each_with_index { |src, arity| begin if fn == :call and (src.is_a?(Proc) or src.is_a?(Method)) and (src.arity == arity or src.arity == -1) values = @stack.slice!(0, arity + 1).reverse return values[0].call(*values[1..-1]) elsif src.respond_to?(fn) and (src.method(fn).arity == arity or src.method(fn).arity == -1) values = @stack.slice!(0, arity + 1).reverse return values[0].send(fn, *values[1..-1]) end rescue ArgumentsError end } # check if /fn/ is a valid method of Kernel or Math [Kernel, Math].each { |src| begin if src.respond_to? fn values = @stack.slice!(0, src.method(fn).arity).reverse return src.send(fn, *values) end rescue end } raise "Couldn't execute function on stack item, DC, Kernel, or Math" end |
#parse_code(stream) ⇒ Object
138 139 140 141 142 143 144 |
# File 'lib/rprb.rb', line 138 def parse_code(stream) if stream.is_a? Array stream else raise "#{stream.inspect} isn't code!" end end |
#read(val) ⇒ Object
107 108 109 |
# File 'lib/rprb.rb', line 107 def read(val) @reader.read without_comments(val) end |
#stack ⇒ Object
103 104 105 |
# File 'lib/rprb.rb', line 103 def stack @stack.dup end |
#without_comments(string) ⇒ Object
111 112 113 114 115 |
# File 'lib/rprb.rb', line 111 def without_comments(string) string.lines.map do |line| line.gsub(/#.*$/, '') end.join('') end |