fork download
  1. class Object
  2. @binding = binding
  3.  
  4. class << self
  5. attr_accessor :binding
  6. end
  7. end
  8.  
  9. class Proc
  10. def binding_eval(code)
  11. eval(code, binding)
  12. end
  13. end
  14.  
  15. class MyStruct
  16.  
  17.  
  18.  
  19. end
  20.  
  21. class MyThunkTarget
  22.  
  23. def work
  24. puts "Hi."
  25. puts foo_obj
  26.  
  27. end
  28. end
  29.  
  30. class AssociativeArray < Array
  31. def initialize *args
  32. @collection = []
  33. super *args
  34. end
  35.  
  36. def insert arg0, arg1=nil
  37. unless arg1.nil?
  38. @collection << KeyValuePair.new(arg1, arg0)
  39. else
  40. @collection << arg0
  41. end
  42. end
  43.  
  44. def << item
  45. insert(item)
  46. end
  47.  
  48. def [] arg0
  49. result = nil
  50. @collection.each do |it|; result = it.value if it.key == arg0; end
  51.  
  52. raise IndexError, sprintf("Index '%s' outside array bounds.", arg0) if result.nil?
  53. result
  54. end
  55.  
  56. def include? arg0
  57. result = false
  58.  
  59. @collection.each do |it|; result = true if it.key == arg0; end
  60.  
  61. result
  62. end
  63. end
  64.  
  65. class KeyValuePair
  66. attr_accessor :key
  67. attr_accessor :value
  68.  
  69. def initialize arg0, arg1=nil
  70. unless arg0.is_a?(Array) and not arg1.nil?
  71. @key, @value = arg0
  72. else
  73. @key, @value = arg0, arg1
  74. end
  75. end
  76.  
  77. def == arg0
  78. @key == arg0
  79. end
  80. end
  81.  
  82. class Thunk
  83. public
  84. def initialize(type_of, *args)
  85. @target, @params = type_of.new, AssociativeArray.new
  86. args.each { |i| @params << KeyValuePair.new(i) }
  87. end
  88.  
  89. def method_missing(fn, *args)
  90.  
  91. this = @target.method(fn.to_sym).to_proc
  92. locals = @target.method(fn.to_sym).send(:local_variables)
  93.  
  94.  
  95.  
  96.  
  97. puts "["
  98. puts locals
  99. puts "]"
  100.  
  101. puts ""
  102. puts ""
  103. this.call *args
  104. puts ""
  105. rescue NameError => e
  106. name = sprintf( "@%s", e.name ).to_sym
  107. metaclass = class << @target; self; end
  108.  
  109. raise e unless @params.include? e.name
  110.  
  111. fieldname_get, fieldname_set = e.name.to_sym, sprintf("%s=", e.name).to_sym
  112. fieldname_attr = sprintf("@%s", e.name).to_sym
  113.  
  114. metaclass.instance_exec(fieldname_set, fieldname_get, fieldname_attr) do
  115. |set, get, fieldname|
  116.  
  117. define_method( fieldname_set ) do |value|
  118. instance_variable_set( fieldname, value )
  119. end
  120.  
  121. define_method( fieldname_get ) do
  122. instance_variable_get( fieldname )
  123. end
  124. end
  125.  
  126. @target.instance_variable_set( fieldname_attr, @params[e.name] )
  127. retry
  128. end
  129. end
  130.  
  131. arg0 = "Hello, world!"
  132. arg1 = MyStruct.new
  133.  
  134. t = Thunk.new(MyThunkTarget, :foo_obj => arg0, :my_struct => arg1)
  135. t.work
  136.  
Runtime error #stdin #stdout #stderr 0.02s 7428KB
stdin
Standard input is empty
stdout
[
fn
args
this
locals
e
name
metaclass
fieldname_get
fieldname_set
fieldname_attr
]


Hi.
stderr
prog.rb:25:in `work': undefined local variable or method `foo_obj' for #<MyThunkTarget:0x89b9148> (NameError)
	from prog.rb:103:in `call'
	from prog.rb:103:in `method_missing'
	from prog.rb:135:in `<main>'