Class: GenText::VM
- Inherits:
-
Object
- Object
- GenText::VM
- Defined in:
- lib/gen_text/vm.rb
Defined Under Namespace
Classes: RescuePoint
Instance Attribute Summary collapse
- #out ⇒ IO readonly
- #pc ⇒ Integer readonly
Class Method Summary collapse
-
.may_set_out_pos?(program) ⇒ Boolean
True if
program
may result in calling IO#pos= and false otherwise.
Instance Method Summary collapse
- #call(addr) ⇒ void
- #capture(binding_, name, discard_output) ⇒ void
- #dec ⇒ void
-
#eval_ruby_code(binding_, ruby_code, file, line) ⇒ void
#push(eval(
ruby_code
,file
,line
)). - #gen ⇒ void
-
#generated_from(*args) ⇒ void
NOP.
- #goto(addr) ⇒ void
- #goto_if(addr) ⇒ void
-
#goto_if_not_0(addr) ⇒ void
If the value on the stack != 0 then #goto(+addr).
-
#goto_if_rand_gt(v, addr) ⇒ void
If rand >
v
then #goto(addr). -
#halt ⇒ void
Sets #halted? to true.
- #halted? ⇒ Boolean
-
#pop ⇒ Object
Pops the value from the stack.
-
#push(o) ⇒ void
Pushes
o
to the stack. -
#push_dup(o) ⇒ void
#push(o.dup).
- #push_pos ⇒ void
-
#push_rand(r = nil) ⇒ void
#push(rand(
r
) ifr
is specified; rand() otherwise). -
#push_rescue_point(pc = nil) ⇒ void
#push(#out‘s IO#pos, #pc as RescuePoint).
-
#rescue_(on_failure) ⇒ void
#pops until a RescuePoint is found then restore #out and #pc from the RescuePoint.
- #ret ⇒ void
-
#run(program, out, do_not_run = false) ⇒ void
Executes
program
. -
#weighed_choice ⇒ void
Let stack contains
wa
= [[weight1, address1], [weight2, address2], …].
Instance Attribute Details
#pc ⇒ Integer (readonly)
56 57 58 |
# File 'lib/gen_text/vm.rb', line 56 def pc @pc end |
Class Method Details
.may_set_out_pos?(program) ⇒ Boolean
Returns true if program
may result in calling IO#pos= and false otherwise.
9 10 11 12 13 |
# File 'lib/gen_text/vm.rb', line 9 def self.may_set_out_pos?(program) program.any? do |instruction| [:rescue_, :capture].include? instruction.first end end |
Instance Method Details
#call(addr) ⇒ void
This method returns an undefined value.
244 245 246 247 |
# File 'lib/gen_text/vm.rb', line 244 def call(addr) @stack.push(@pc + 1) @pc = addr end |
#capture(binding_, name, discard_output) ⇒ void
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/gen_text/vm.rb', line 180 def capture(binding_, name, discard_output) capture_start_pos = @stack.pop capture_end_pos = @out.pos captured_string = begin @out.pos = capture_start_pos @out.read(capture_end_pos - capture_start_pos) end @out.pos = if discard_output then capture_start_pos else capture_end_pos end binding_.eval("#{name} = #{captured_string.inspect}") @pc += 1 end |
#dec ⇒ void
This method returns an undefined value.
126 127 128 129 |
# File 'lib/gen_text/vm.rb', line 126 def dec @stack[-1] -= 1 @pc += 1 end |
#eval_ruby_code(binding_, ruby_code, file, line) ⇒ void
This method returns an undefined value.
#push(eval(ruby_code
, file
, line
))
204 205 206 207 |
# File 'lib/gen_text/vm.rb', line 204 def eval_ruby_code(binding_, ruby_code, file, line) @stack.push binding_.eval(ruby_code, file, line) @pc += 1 end |
#gen ⇒ void
166 167 168 169 |
# File 'lib/gen_text/vm.rb', line 166 def gen @out.write @stack.pop @pc += 1 end |
#generated_from(*args) ⇒ void
This method returns an undefined value.
NOP
76 77 78 |
# File 'lib/gen_text/vm.rb', line 76 def generated_from(*args) @pc += 1 end |
#goto(addr) ⇒ void
This method returns an undefined value.
159 160 161 |
# File 'lib/gen_text/vm.rb', line 159 def goto(addr) @pc = addr end |
#goto_if(addr) ⇒ void
117 118 119 120 121 122 123 |
# File 'lib/gen_text/vm.rb', line 117 def goto_if(addr) if @stack.pop then @pc = addr else @pc += 1 end end |
#goto_if_not_0(addr) ⇒ void
This method returns an undefined value.
If the value on the stack != 0 then #goto(+addr).
135 136 137 138 139 140 141 |
# File 'lib/gen_text/vm.rb', line 135 def goto_if_not_0(addr) if @stack.last != 0 then @pc += 1 else @pc = addr end end |
#goto_if_rand_gt(v, addr) ⇒ void
This method returns an undefined value.
If rand > v
then #goto(addr)
149 150 151 152 153 154 155 |
# File 'lib/gen_text/vm.rb', line 149 def goto_if_rand_gt(v, addr) if rand > v then @pc = addr else @pc += 1 end end |
#halt ⇒ void
This method returns an undefined value.
Sets #halted? to true.
69 70 71 |
# File 'lib/gen_text/vm.rb', line 69 def halt @halted = true end |
#halted? ⇒ Boolean
62 63 64 |
# File 'lib/gen_text/vm.rb', line 62 def halted? @halted end |
#pop ⇒ Object
Pops the value from the stack.
108 109 110 111 |
# File 'lib/gen_text/vm.rb', line 108 def pop @stack.pop @pc += 1 end |
#push(o) ⇒ void
This method returns an undefined value.
Pushes o
to the stack.
84 85 86 87 |
# File 'lib/gen_text/vm.rb', line 84 def push(o) @stack.push o @pc += 1 end |
#push_dup(o) ⇒ void
This method returns an undefined value.
#push(o.dup)
93 94 95 |
# File 'lib/gen_text/vm.rb', line 93 def push_dup(o) push(o.dup) end |
#push_pos ⇒ void
212 213 214 215 |
# File 'lib/gen_text/vm.rb', line 212 def push_pos @stack.push(@out.pos) @pc += 1 end |
#push_rand(r = nil) ⇒ void
This method returns an undefined value.
#push(rand(r
) if r
is specified; rand() otherwise)
101 102 103 |
# File 'lib/gen_text/vm.rb', line 101 def push_rand(r = nil) push(if r then rand(r) else rand end) end |
#push_rescue_point(pc = nil) ⇒ void
This method returns an undefined value.
#push(#out‘s IO#pos, #pc as RescuePoint)
221 222 223 224 |
# File 'lib/gen_text/vm.rb', line 221 def push_rescue_point(pc = nil) @stack.push RescuePoint[(pc or @pc), @out.pos] @pc += 1 end |
#rescue_(on_failure) ⇒ void
This method returns an undefined value.
#pops until a RescuePoint is found then restore #out and #pc from the RescuePoint.
231 232 233 234 235 236 237 238 239 240 |
# File 'lib/gen_text/vm.rb', line 231 def rescue_(on_failure) @stack.pop until @stack.empty? or @stack.last.is_a? RescuePoint if @stack.empty? then on_failure.() else rescue_point = @stack.pop @pc = rescue_point.pc @out.pos = rescue_point.out_pos end end |
#ret ⇒ void
This method returns an undefined value.
250 251 252 |
# File 'lib/gen_text/vm.rb', line 250 def ret @pc = @stack.pop end |
#run(program, out, do_not_run = false) ⇒ void
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/gen_text/vm.rb', line 26 def run(program, out, do_not_run = false) # if $DEBUG STDERR.puts "PROGRAM:" program.each_with_index do |instruction, addr| STDERR.puts " #{addr}: #{inspect_instruction(instruction)}" end end # return if do_not_run # Init. @stack = [] @out = out @pc = 0 @halted = false # Run. STDERR.puts "RUN TRACE:" if $DEBUG until halted? instruction = program[@pc] method_id, *args = *instruction STDERR.puts " #{@pc}: #{inspect_instruction(instruction)}" if $DEBUG self.__send__(method_id, *args) if $DEBUG then STDERR.puts " PC: #{@pc}" STDERR.puts " STACK: #{@stack.inspect}" end end end |
#weighed_choice ⇒ void
This method returns an undefined value.
Let stack contains wa
= [[weight1, address1], [weight2, address2], …]. This function:
-
Picks a random address from
wa
(the more weight the address has, the more often it is picked); -
Deletes the chosen address from
wa
; -
If there was the only address in
wa
then it does #push(nil); otherwise it does #push_rescue_point; -
#goto(the chosen address).
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/gen_text/vm.rb', line 265 def weighed_choice weights_and_addresses = @stack.last # If no alternatives left... if weights_and_addresses.size == 1 then _, address = *weights_and_addresses.first @stack.push nil @pc = address # If there are alternatives... else chosen_weight_and_address = sample_weighed(weights_and_addresses) weights_and_addresses.delete chosen_weight_and_address _, chosen_address = *chosen_weight_and_address push_rescue_point @pc = chosen_address end end |