Class: Twostroke::Runtime::VM::Frame
- Inherits:
-
Object
- Object
- Twostroke::Runtime::VM::Frame
- Defined in:
- lib/twostroke/runtime/vm_frame.rb
Instance Attribute Summary collapse
-
#catch_stack ⇒ Object
readonly
Returns the value of attribute catch_stack.
-
#enum_stack ⇒ Object
readonly
Returns the value of attribute enum_stack.
-
#exception ⇒ Object
readonly
Returns the value of attribute exception.
-
#finally_stack ⇒ Object
readonly
Returns the value of attribute finally_stack.
-
#insns ⇒ Object
readonly
Returns the value of attribute insns.
-
#ip ⇒ Object
readonly
Returns the value of attribute ip.
-
#scope ⇒ Object
readonly
Returns the value of attribute scope.
-
#sp_stack ⇒ Object
readonly
Returns the value of attribute sp_stack.
-
#stack ⇒ Object
readonly
Returns the value of attribute stack.
-
#vm ⇒ Object
readonly
Returns the value of attribute vm.
Instance Method Summary collapse
- #_throw(arg) ⇒ Object
- #add(arg) ⇒ Object
- #and(arg) ⇒ Object
- #arguments_object ⇒ Object
- #array(arg) ⇒ Object
- #call(arg) ⇒ Object
- #callee(arg) ⇒ Object
- #close(arg) ⇒ Object
- #dec(arg) ⇒ Object
- #delete(arg) ⇒ Object
- #deleteg(arg) ⇒ Object
- #div(arg) ⇒ Object
- #dup(arg) ⇒ Object
- #enum(arg) ⇒ Object
- #enumnext(arg) ⇒ Object
- #eq(arg) ⇒ Object
- #execute(scope, this = nil, args = []) ⇒ Object
- #false(arg) ⇒ Object
- #gt(arg) ⇒ Object
- #gte(arg) ⇒ Object
- #in(arg) ⇒ Object
- #inc(arg) ⇒ Object
- #index(arg) ⇒ Object
-
#initialize(vm, section, callee = nil) ⇒ Frame
constructor
A new instance of Frame.
- #instanceof(arg) ⇒ Object
- #jiee(arg) ⇒ Object
- #jif(arg) ⇒ Object
- #jit(arg) ⇒ Object
- #jmp(arg) ⇒ Object
- #lt(arg) ⇒ Object
- #lte(arg) ⇒ Object
- #member(arg) ⇒ Object
- #mod(arg) ⇒ Object
- #mul(arg) ⇒ Object
- #negate(arg) ⇒ Object
- #newcall(arg) ⇒ Object
- #not(arg) ⇒ Object
- #null(arg) ⇒ Object
- #number(arg) ⇒ Object
- #object(arg) ⇒ Object
- #or(arg) ⇒ Object
- #pop(arg) ⇒ Object
- #popcatch(arg) ⇒ Object
- #popenum(arg) ⇒ Object
- #popfinally(arg) ⇒ Object
- #popscope(arg) ⇒ Object
- #popsp(arg) ⇒ Object
-
#push(arg) ⇒ Object
instructions.
- #pushcatch(arg) ⇒ Object
- #pushfinally(arg) ⇒ Object
- #pushsp(arg) ⇒ Object
- #regexp(arg) ⇒ Object
- #ret(arg) ⇒ Object
- #sal(arg) ⇒ Object
- #sar(arg) ⇒ Object
- #seq(arg) ⇒ Object
- #set(arg) ⇒ Object
- #setindex(arg) ⇒ Object
- #setprop(arg) ⇒ Object
- #slr(arg) ⇒ Object
- #sub(arg) ⇒ Object
- #this(arg) ⇒ Object
- #thiscall(arg) ⇒ Object
- #true(arg) ⇒ Object
- #typeof(arg) ⇒ Object
- #undefined(arg) ⇒ Object
- #with(arg) ⇒ Object
- #xor(arg) ⇒ Object
Constructor Details
#initialize(vm, section, callee = nil) ⇒ Frame
Returns a new instance of Frame.
5 6 7 8 9 10 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 5 def initialize(vm, section, callee = nil) @vm = vm @section = section @insns = vm.bytecode[section] @callee = callee end |
Instance Attribute Details
#catch_stack ⇒ Object (readonly)
Returns the value of attribute catch_stack.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def catch_stack @catch_stack end |
#enum_stack ⇒ Object (readonly)
Returns the value of attribute enum_stack.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def enum_stack @enum_stack end |
#exception ⇒ Object (readonly)
Returns the value of attribute exception.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def exception @exception end |
#finally_stack ⇒ Object (readonly)
Returns the value of attribute finally_stack.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def finally_stack @finally_stack end |
#insns ⇒ Object (readonly)
Returns the value of attribute insns.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def insns @insns end |
#ip ⇒ Object (readonly)
Returns the value of attribute ip.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def ip @ip end |
#scope ⇒ Object (readonly)
Returns the value of attribute scope.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def scope @scope end |
#sp_stack ⇒ Object (readonly)
Returns the value of attribute sp_stack.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def sp_stack @sp_stack end |
#stack ⇒ Object (readonly)
Returns the value of attribute stack.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def stack @stack end |
#vm ⇒ Object (readonly)
Returns the value of attribute vm.
3 4 5 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 3 def vm @vm end |
Instance Method Details
#_throw(arg) ⇒ Object
185 186 187 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 185 def _throw(arg) throw :exception, stack.pop end |
#add(arg) ⇒ Object
286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 286 def add(arg) r = stack.pop l = stack.pop right = Types.to_primitive r left = Types.to_primitive l if left.is_a?(Types::String) || right.is_a?(Types::String) stack.push Types::String.new(Types.to_string(left).string + Types.to_string(right).string) else stack.push Types::Number.new(Types.to_number(left).number + Types.to_number(right).number) end end |
#and(arg) ⇒ Object
323 324 325 326 327 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 323 def and(arg) right = Types.to_int32 stack.pop left = Types.to_int32 stack.pop stack.push Types::Number.new(left & right) end |
#arguments_object ⇒ Object
12 13 14 15 16 17 18 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 12 def arguments_object arguments = Types::Object.new @args.each_with_index { |arg,i| arguments.put i.to_s, arg } arguments.put "length", Types::Number.new(@args.size) arguments.put "callee", @callee arguments end |
#array(arg) ⇒ Object
250 251 252 253 254 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 250 def array(arg) args = [] arg.times { args.unshift stack.pop } stack.push Types::Array.new(args) end |
#call(arg) ⇒ Object
89 90 91 92 93 94 95 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 89 def call(arg) args = [] arg.times { args.unshift @stack.pop } fun = stack.pop Lib.throw_type_error "called non callable" unless fun.respond_to?(:call) stack.push fun.call(scope, scope.global_scope.root_object, args) end |
#callee(arg) ⇒ Object
386 387 388 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 386 def callee(arg) stack.push @callee end |
#close(arg) ⇒ Object
378 379 380 381 382 383 384 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 378 def close(arg) name = vm.bytecode[arg].select { |ins,arg| ins == :".name" }.map { |ins,arg| arg }.first arguments = vm.bytecode[arg].select { |ins,arg| ins == :".arg" }.map(&:last).map(&:to_s) scope = @scope fun = Types::Function.new(->(outer_scope, this, args) { VM::Frame.new(vm, arg, fun).execute(scope.close, this, args) }, "...", name || "", arguments) stack.push fun end |
#dec(arg) ⇒ Object
237 238 239 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 237 def dec(arg) stack.push Types::Number.new(Types.to_number(stack.pop).number - 1) end |
#delete(arg) ⇒ Object
134 135 136 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 134 def delete(arg) Types.to_object(stack.pop).delete arg.to_s end |
#deleteg(arg) ⇒ Object
130 131 132 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 130 def deleteg(arg) scope.global_scope.root_object.delete arg.to_s end |
#div(arg) ⇒ Object
311 312 313 314 315 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 311 def div(arg) right = Types.to_number(stack.pop).number left = Types.to_number(stack.pop).number stack.push Types::Number.new(left / right.to_f) end |
#dup(arg) ⇒ Object
121 122 123 124 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 121 def dup(arg) n = arg || 1 stack.push *stack[-n..-1] end |
#enum(arg) ⇒ Object
144 145 146 147 148 149 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 144 def enum(arg) props = [] obj = stack.pop Types.to_object(obj).each_enumerable_property { |p| props.push p } unless obj.is_a?(Types::Null) || obj.is_a?(Types::Undefined) @enum_stack.push [props, 0] end |
#enumnext(arg) ⇒ Object
151 152 153 154 155 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 151 def enumnext(arg) enum = @enum_stack.last stack.push Types::String.new(enum[0][enum[1]]) enum[1] += 1 end |
#eq(arg) ⇒ Object
189 190 191 192 193 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 189 def eq(arg) b = stack.pop a = stack.pop stack.push Types::Boolean.new(Types.eq(a, b)) end |
#execute(scope, this = nil, args = []) ⇒ Object
20 21 22 23 24 25 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 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 20 def execute(scope, this = nil, args = []) @scope = scope || Scope.new(vm.global_scope) @stack = [] @sp_stack = [] @catch_stack = [] @finally_stack = [] @enum_stack = [] @ip = 0 @return = false @this = this || @scope.global_scope.root_object @args = args if @callee # the arguments object is only available within functions scope.declare :arguments scope.set_var :arguments, arguments_object end until @return ins, arg = *insns[ip] st = @stack.size @ip += 1 if respond_to? ins if @exception = catch(:exception) { public_send ins, arg; nil } throw :exception, @exception if catch_stack.empty? @ip = catch_stack.last end else error! "unknown instruction #{ins}" end end stack.last end |
#false(arg) ⇒ Object
209 210 211 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 209 def false(arg) stack.push Types::Boolean.new(false) end |
#gt(arg) ⇒ Object
356 357 358 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 356 def gt(arg) comparison_oper :> end |
#gte(arg) ⇒ Object
360 361 362 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 360 def gte(arg) comparison_oper :>= end |
#in(arg) ⇒ Object
138 139 140 141 142 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 138 def in(arg) obj = Types.to_object stack.pop idx = Types.to_string stack.pop stack.push Types::Boolean.new(obj.has_property idx.string) end |
#inc(arg) ⇒ Object
233 234 235 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 233 def inc(arg) stack.push Types::Number.new(Types.to_number(stack.pop).number + 1) end |
#index(arg) ⇒ Object
245 246 247 248 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 245 def index(arg) index = Types.to_string(stack.pop).string stack.push(Types.to_object(stack.pop).get(index) || Types::Undefined.new) end |
#instanceof(arg) ⇒ Object
372 373 374 375 376 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 372 def instanceof(arg) r = stack.pop l = stack.pop stack.push Types::Boolean.new(r.has_instance l) end |
#jiee(arg) ⇒ Object
157 158 159 160 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 157 def jiee(arg) enum = @enum_stack.last @ip = arg if enum[1] >= enum[0].size end |
#jif(arg) ⇒ Object
217 218 219 220 221 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 217 def jif(arg) if Types.is_falsy stack.pop @ip = arg.to_i end end |
#jit(arg) ⇒ Object
223 224 225 226 227 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 223 def jit(arg) if Types.is_truthy stack.pop @ip = arg.to_i end end |
#jmp(arg) ⇒ Object
213 214 215 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 213 def jmp(arg) @ip = arg.to_i end |
#lt(arg) ⇒ Object
348 349 350 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 348 def lt(arg) comparison_oper :< end |
#lte(arg) ⇒ Object
352 353 354 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 352 def lte(arg) comparison_oper :<= end |
#member(arg) ⇒ Object
126 127 128 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 126 def member(arg) stack.push Types.to_object(stack.pop).get(arg.to_s) end |
#mod(arg) ⇒ Object
317 318 319 320 321 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 317 def mod(arg) right = Types.to_number(stack.pop).number left = Types.to_number(stack.pop).number stack.push Types::Number.new(left % right) end |
#mul(arg) ⇒ Object
305 306 307 308 309 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 305 def mul(arg) right = Types.to_number(stack.pop).number left = Types.to_number(stack.pop).number stack.push Types::Number.new(left * right) end |
#negate(arg) ⇒ Object
398 399 400 401 402 403 404 405 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 398 def negate(arg) n = Types.to_number(stack.pop).number if n.zero? stack.push Types::Number.new(-n.to_f) # to preserve javascript's 0/-0 semantics else stack.push Types::Number.new(-n) end end |
#newcall(arg) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 105 def newcall(arg) args = [] arg.times { args.unshift @stack.pop } fun = stack.pop Lib.throw_type_error "called non callable" unless fun.respond_to?(:call) obj = Types::Object.new obj.construct prototype: fun.get("prototype"), _class: fun do retn = fun.call(scope, obj, args) if retn.is_a?(Types::Undefined) stack.push obj else stack.push retn end end end |
#not(arg) ⇒ Object
229 230 231 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 229 def not(arg) stack.push Types::Boolean.new(Types.is_falsy(stack.pop)) end |
#null(arg) ⇒ Object
201 202 203 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 201 def null(arg) stack.push Types::Null.new end |
#number(arg) ⇒ Object
260 261 262 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 260 def number(arg) stack.push Types.to_number(stack.pop) end |
#object(arg) ⇒ Object
390 391 392 393 394 395 396 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 390 def object(arg) obj = Types::Object.new kvs = [] arg.reverse_each { |a| kvs << [a, stack.pop] } kvs.reverse_each { |kv| obj.put kv[0].to_s, kv[1] } stack.push obj end |
#or(arg) ⇒ Object
329 330 331 332 333 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 329 def or(arg) right = Types.to_int32 stack.pop left = Types.to_int32 stack.pop stack.push Types::Number.new(left | right) end |
#pop(arg) ⇒ Object
241 242 243 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 241 def pop(arg) stack.pop end |
#popcatch(arg) ⇒ Object
427 428 429 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 427 def popcatch(arg) catch_stack.pop end |
#popenum(arg) ⇒ Object
162 163 164 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 162 def popenum(arg) @enum_stack.pop end |
#popfinally(arg) ⇒ Object
435 436 437 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 435 def popfinally(arg) finally_stack.pop end |
#popscope(arg) ⇒ Object
411 412 413 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 411 def popscope(arg) @scope = @scope.parent end |
#popsp(arg) ⇒ Object
419 420 421 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 419 def popsp(arg) @stack = stack[0...sp_stack.pop] end |
#push(arg) ⇒ Object
instructions
75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 75 def push(arg) if arg.is_a? Symbol stack.push scope.get_var(arg) elsif arg.is_a?(Fixnum) || arg.is_a?(Float) stack.push Types::Number.new(arg) elsif arg.is_a?(Bignum) stack.push Types::Number.new(arg.to_f) elsif arg.is_a?(String) stack.push Types::String.new(arg) else error! "bad argument to push instruction" end end |
#pushcatch(arg) ⇒ Object
423 424 425 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 423 def pushcatch(arg) catch_stack.push arg end |
#pushfinally(arg) ⇒ Object
431 432 433 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 431 def pushfinally(arg) finally_stack.push arg end |
#pushsp(arg) ⇒ Object
415 416 417 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 415 def pushsp(arg) sp_stack.push stack.size end |
#regexp(arg) ⇒ Object
264 265 266 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 264 def regexp(arg) stack.push Types::RegExp.new(*arg) end |
#ret(arg) ⇒ Object
177 178 179 180 181 182 183 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 177 def ret(arg) if finally_stack.empty? @return = true else @ip = finally_stack.last end end |
#sal(arg) ⇒ Object
268 269 270 271 272 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 268 def sal(arg) r = Types.to_uint32(stack.pop) & 31 l = Types.to_int32 stack.pop stack.push Types::Number.new(l << r) end |
#sar(arg) ⇒ Object
274 275 276 277 278 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 274 def sar(arg) r = Types.to_uint32(stack.pop) & 31 l = Types.to_int32 stack.pop stack.push Types::Number.new(l >> r) end |
#seq(arg) ⇒ Object
195 196 197 198 199 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 195 def seq(arg) b = stack.pop a = stack.pop stack.push Types::Boolean.new(Types.seq(a, b)) end |
#set(arg) ⇒ Object
166 167 168 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 166 def set(arg) scope.set_var arg, stack.last end |
#setindex(arg) ⇒ Object
341 342 343 344 345 346 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 341 def setindex(arg) val = stack.pop index = Types.to_string(stack.pop).string Types.to_object(stack.pop).put index, val stack.push val end |
#setprop(arg) ⇒ Object
170 171 172 173 174 175 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 170 def setprop(arg) val = stack.pop obj = stack.pop obj.put arg.to_s, val stack.push val end |
#slr(arg) ⇒ Object
280 281 282 283 284 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 280 def slr(arg) r = Types.to_uint32(stack.pop) & 31 l = Types.to_uint32 stack.pop stack.push Types::Number.new(l >> r) end |
#sub(arg) ⇒ Object
299 300 301 302 303 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 299 def sub(arg) right = Types.to_number(stack.pop).number left = Types.to_number(stack.pop).number stack.push Types::Number.new(left - right) end |
#this(arg) ⇒ Object
439 440 441 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 439 def this(arg) stack.push @this end |
#thiscall(arg) ⇒ Object
97 98 99 100 101 102 103 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 97 def thiscall(arg) args = [] arg.times { args.unshift stack.pop } fun = stack.pop Lib.throw_type_error "called non callable" unless fun.respond_to?(:call) stack.push fun.call(scope, Types.to_object(stack.pop), args) end |
#true(arg) ⇒ Object
205 206 207 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 205 def true(arg) stack.push Types::Boolean.new(true) end |
#typeof(arg) ⇒ Object
364 365 366 367 368 369 370 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 364 def typeof(arg) if arg stack.push Types::String.new(scope.has_var(arg) ? scope.get_var(arg).typeof : "undefined") else stack.push Types::String.new(stack.pop.typeof) end end |
#undefined(arg) ⇒ Object
256 257 258 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 256 def undefined(arg) stack.push Types::Undefined.new end |
#with(arg) ⇒ Object
407 408 409 |
# File 'lib/twostroke/runtime/vm_frame.rb', line 407 def with(arg) @scope = ObjectScope.new stack.pop, @scope end |