ruby-internal 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +59 -0
- data/LGPL +515 -0
- data/LICENSE +9 -0
- data/README +31 -0
- data/Rakefile +20 -0
- data/TODO +9 -0
- data/example/README +5 -0
- data/example/simple_client.rb +12 -0
- data/example/simple_server.rb +11 -0
- data/example/triangle_client.rb +7 -0
- data/example/triangle_server.rb +24 -0
- data/ext/cached/ruby-1.8.0/internal/binding/block.h +37 -0
- data/ext/cached/ruby-1.8.0/internal/method/method.h +19 -0
- data/ext/cached/ruby-1.8.0/internal/module/classpath.c +27 -0
- data/ext/cached/ruby-1.8.0/internal/module/classpath.h +14 -0
- data/ext/cached/ruby-1.8.0/internal/node/block.h +37 -0
- data/ext/cached/ruby-1.8.0/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.0/internal/node/node_type_descrip.c +155 -0
- data/ext/cached/ruby-1.8.0/internal/node/nodeinfo.c +5741 -0
- data/ext/cached/ruby-1.8.0/internal/node/nodeinfo.h +69 -0
- data/ext/cached/ruby-1.8.0/internal/proc/block.h +37 -0
- data/ext/cached/ruby-1.8.0/internal/tag/tag.h +15 -0
- data/ext/cached/ruby-1.8.0/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.0/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.0/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.1/internal/binding/block.h +31 -0
- data/ext/cached/ruby-1.8.1/internal/method/method.h +19 -0
- data/ext/cached/ruby-1.8.1/internal/module/classpath.c +27 -0
- data/ext/cached/ruby-1.8.1/internal/module/classpath.h +14 -0
- data/ext/cached/ruby-1.8.1/internal/node/block.h +31 -0
- data/ext/cached/ruby-1.8.1/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.1/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.1/internal/node/nodeinfo.c +5733 -0
- data/ext/cached/ruby-1.8.1/internal/node/nodeinfo.h +69 -0
- data/ext/cached/ruby-1.8.1/internal/proc/block.h +31 -0
- data/ext/cached/ruby-1.8.1/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.1/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.1/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.1/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.2/internal/binding/block.h +32 -0
- data/ext/cached/ruby-1.8.2/internal/method/method.h +19 -0
- data/ext/cached/ruby-1.8.2/internal/module/classpath.c +45 -0
- data/ext/cached/ruby-1.8.2/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.8.2/internal/node/block.h +32 -0
- data/ext/cached/ruby-1.8.2/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.2/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.2/internal/node/nodeinfo.c +5733 -0
- data/ext/cached/ruby-1.8.2/internal/node/nodeinfo.h +69 -0
- data/ext/cached/ruby-1.8.2/internal/proc/block.h +32 -0
- data/ext/cached/ruby-1.8.2/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.2/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.2/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.2/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.3/internal/binding/block.h +32 -0
- data/ext/cached/ruby-1.8.3/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.8.3/internal/module/classpath.c +45 -0
- data/ext/cached/ruby-1.8.3/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.8.3/internal/node/block.h +32 -0
- data/ext/cached/ruby-1.8.3/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.3/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.3/internal/node/nodeinfo.c +5733 -0
- data/ext/cached/ruby-1.8.3/internal/node/nodeinfo.h +69 -0
- data/ext/cached/ruby-1.8.3/internal/proc/block.h +32 -0
- data/ext/cached/ruby-1.8.3/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.3/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.3/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.3/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.4/internal/binding/block.h +32 -0
- data/ext/cached/ruby-1.8.4/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.8.4/internal/module/classpath.c +45 -0
- data/ext/cached/ruby-1.8.4/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.8.4/internal/node/block.h +32 -0
- data/ext/cached/ruby-1.8.4/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.4/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.4/internal/node/nodeinfo.c +5733 -0
- data/ext/cached/ruby-1.8.4/internal/node/nodeinfo.h +69 -0
- data/ext/cached/ruby-1.8.4/internal/proc/block.h +32 -0
- data/ext/cached/ruby-1.8.4/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.4/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.4/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.4/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.5/internal/binding/block.h +32 -0
- data/ext/cached/ruby-1.8.5/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.8.5/internal/module/classpath.c +45 -0
- data/ext/cached/ruby-1.8.5/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.8.5/internal/node/block.h +32 -0
- data/ext/cached/ruby-1.8.5/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.5/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.5/internal/node/nodeinfo.c +5732 -0
- data/ext/cached/ruby-1.8.5/internal/node/nodeinfo.h +67 -0
- data/ext/cached/ruby-1.8.5/internal/proc/block.h +32 -0
- data/ext/cached/ruby-1.8.5/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.5/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.5/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.5/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.6/internal/binding/block.h +32 -0
- data/ext/cached/ruby-1.8.6/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.8.6/internal/module/classpath.c +45 -0
- data/ext/cached/ruby-1.8.6/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.8.6/internal/node/block.h +32 -0
- data/ext/cached/ruby-1.8.6/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.6/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.6/internal/node/nodeinfo.c +5732 -0
- data/ext/cached/ruby-1.8.6/internal/node/nodeinfo.h +67 -0
- data/ext/cached/ruby-1.8.6/internal/proc/block.h +32 -0
- data/ext/cached/ruby-1.8.6/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.6/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.6/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.6/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.8.7/internal/binding/block.h +32 -0
- data/ext/cached/ruby-1.8.7/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.8.7/internal/module/classpath.c +45 -0
- data/ext/cached/ruby-1.8.7/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.8.7/internal/node/block.h +32 -0
- data/ext/cached/ruby-1.8.7/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.8.7/internal/node/node_type_descrip.c +154 -0
- data/ext/cached/ruby-1.8.7/internal/node/nodeinfo.c +5732 -0
- data/ext/cached/ruby-1.8.7/internal/node/nodeinfo.h +67 -0
- data/ext/cached/ruby-1.8.7/internal/proc/block.h +32 -0
- data/ext/cached/ruby-1.8.7/internal/tag/tag.h +16 -0
- data/ext/cached/ruby-1.8.7/internal/vm/instruction/insns_info.c +39 -0
- data/ext/cached/ruby-1.8.7/internal/vm/instruction/insns_info.h +21 -0
- data/ext/cached/ruby-1.8.7/internal/vm/iseq/insns_info.inc +12 -0
- data/ext/cached/ruby-1.9.0/internal/binding/block.h +12 -0
- data/ext/cached/ruby-1.9.0/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.9.0/internal/module/classpath.c +42 -0
- data/ext/cached/ruby-1.9.0/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.9.0/internal/node/block.h +12 -0
- data/ext/cached/ruby-1.9.0/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.9.0/internal/node/node_type_descrip.c +149 -0
- data/ext/cached/ruby-1.9.0/internal/node/nodeinfo.c +5579 -0
- data/ext/cached/ruby-1.9.0/internal/node/nodeinfo.h +70 -0
- data/ext/cached/ruby-1.9.0/internal/proc/block.h +12 -0
- data/ext/cached/ruby-1.9.0/internal/tag/tag.h +6 -0
- data/ext/cached/ruby-1.9.0/internal/vm/instruction/insns_info.c +5936 -0
- data/ext/cached/ruby-1.9.0/internal/vm/instruction/insns_info.h +891 -0
- data/ext/cached/ruby-1.9.0/internal/vm/iseq/insns_info.inc +700 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/debug.h +36 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/dln.h +41 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/encdb.h +147 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/eval_intern.h +221 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/gc.h +75 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/id.h +83 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/iseq.h +94 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/node.h +516 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/parse.h +303 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/regenc.h +207 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/regint.h +842 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/regparse.h +351 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/revision.h +1 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/thread_pthread.h +24 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/thread_win32.h +33 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/transcode_data.h +99 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/transdb.h +67 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/version.h +57 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/vm_core.h +663 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/vm_exec.h +187 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/vm_insnhelper.h +191 -0
- data/ext/cached/ruby-1.9.0/internal/yarv-headers/vm_opts.h +51 -0
- data/ext/cached/ruby-1.9.1/internal/binding/block.h +12 -0
- data/ext/cached/ruby-1.9.1/internal/method/method.h +20 -0
- data/ext/cached/ruby-1.9.1/internal/module/classpath.c +42 -0
- data/ext/cached/ruby-1.9.1/internal/module/classpath.h +17 -0
- data/ext/cached/ruby-1.9.1/internal/node/block.h +12 -0
- data/ext/cached/ruby-1.9.1/internal/node/global_entry.h +10 -0
- data/ext/cached/ruby-1.9.1/internal/node/node_type_descrip.c +149 -0
- data/ext/cached/ruby-1.9.1/internal/node/nodeinfo.c +5579 -0
- data/ext/cached/ruby-1.9.1/internal/node/nodeinfo.h +70 -0
- data/ext/cached/ruby-1.9.1/internal/proc/block.h +12 -0
- data/ext/cached/ruby-1.9.1/internal/tag/tag.h +6 -0
- data/ext/cached/ruby-1.9.1/internal/vm/instruction/insns_info.c +5936 -0
- data/ext/cached/ruby-1.9.1/internal/vm/instruction/insns_info.h +891 -0
- data/ext/cached/ruby-1.9.1/internal/vm/iseq/insns_info.inc +700 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/debug.h +36 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/dln.h +41 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/encdb.h +147 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/eval_intern.h +209 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/gc.h +75 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/id.h +184 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/iseq.h +94 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/node.h +516 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/parse.h +303 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/regenc.h +207 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/regint.h +842 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/regparse.h +351 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/revision.h +1 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/thread_pthread.h +24 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/thread_win32.h +33 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/transcode_data.h +99 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/transdb.h +85 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/version.h +60 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_core.h +655 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_exec.h +187 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_insnhelper.h +194 -0
- data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_opts.h +51 -0
- data/ext/internal/binding/binding.c +45 -0
- data/ext/internal/binding/block.h.rpp +44 -0
- data/ext/internal/binding/extconf.rb +6 -0
- data/ext/internal/method/extconf.rb +8 -0
- data/ext/internal/method/method.c +269 -0
- data/ext/internal/method/method.h.rpp +58 -0
- data/ext/internal/module/classpath.c.rpp +29 -0
- data/ext/internal/module/classpath.h.rpp +36 -0
- data/ext/internal/module/extconf.rb +11 -0
- data/ext/internal/module/module.c +797 -0
- data/ext/internal/module/module.h +7 -0
- data/ext/internal/node/block.h.rpp +44 -0
- data/ext/internal/node/builtins.h +41 -0
- data/ext/internal/node/extconf.rb +66 -0
- data/ext/internal/node/global_entry.h.rpp +26 -0
- data/ext/internal/node/node.c +1147 -0
- data/ext/internal/node/node_type_descrip.c.rpp +72 -0
- data/ext/internal/node/node_type_descrip.h +17 -0
- data/ext/internal/node/node_type_descrip.rb +39 -0
- data/ext/internal/node/nodeinfo.c.rpp +587 -0
- data/ext/internal/node/nodeinfo.h.rpp +30 -0
- data/ext/internal/node/nodes.rb +78 -0
- data/ext/internal/node/read_node_h.rb +34 -0
- data/ext/internal/node/ruby_internal_node.h +31 -0
- data/ext/internal/noex/extconf.rb +6 -0
- data/ext/internal/noex/noex.c +44 -0
- data/ext/internal/object/extconf.rb +4 -0
- data/ext/internal/object/object.c +75 -0
- data/ext/internal/proc/block.h.rpp +44 -0
- data/ext/internal/proc/extconf.rb +9 -0
- data/ext/internal/proc/proc.c +331 -0
- data/ext/internal/tag/extconf.rb +3 -0
- data/ext/internal/tag/tag.c +17 -0
- data/ext/internal/tag/tag.h.rpp +22 -0
- data/ext/internal/thread/extconf.rb +3 -0
- data/ext/internal/thread/thread.c +107 -0
- data/ext/internal/vm/constants/constants.c +33 -0
- data/ext/internal/vm/constants/extconf.rb +3 -0
- data/ext/internal/vm/control_frame/control_frame.c +185 -0
- data/ext/internal/vm/control_frame/control_frame.h +18 -0
- data/ext/internal/vm/control_frame/extconf.rb +3 -0
- data/ext/internal/vm/extconf.rb +3 -0
- data/ext/internal/vm/inline_cache/extconf.rb +6 -0
- data/ext/internal/vm/inline_cache/inline_cache.c +79 -0
- data/ext/internal/vm/instruction/extconf.rb +6 -0
- data/ext/internal/vm/instruction/insns_info.c.rpp +213 -0
- data/ext/internal/vm/instruction/insns_info.h.rpp +53 -0
- data/ext/internal/vm/instruction/instruction.c +78 -0
- data/ext/internal/vm/instruction/instruction.h +10 -0
- data/ext/internal/vm/iseq/extconf.rb +7 -0
- data/ext/internal/vm/iseq/insns_info.inc.rpp +30 -0
- data/ext/internal/vm/iseq/internal_iseq.h +9 -0
- data/ext/internal/vm/iseq/iseq.c +555 -0
- data/ext/internal/vm/vm.c +55 -0
- data/ext/mkmf-ruby-internal.rb +111 -0
- data/ext/ruby_source_dir.rb +24 -0
- data/ext/rubypp.rb +97 -0
- data/generate_rdoc.rb +33 -0
- data/lib/internal/binding.rb +1 -0
- data/lib/internal/classtree.rb +55 -0
- data/lib/internal/debug.rb +16 -0
- data/lib/internal/method.rb +1 -0
- data/lib/internal/method/as_code.rb +33 -0
- data/lib/internal/method/as_expression.rb +34 -0
- data/lib/internal/method/signature.rb +442 -0
- data/lib/internal/module.rb +1 -0
- data/lib/internal/module/as_code.rb +45 -0
- data/lib/internal/node.rb +3 -0
- data/lib/internal/node/as_code.rb +233 -0
- data/lib/internal/node/as_expression.rb +619 -0
- data/lib/internal/node/dump.rb +53 -0
- data/lib/internal/node/pp.rb +72 -0
- data/lib/internal/node/to_a.rb +52 -0
- data/lib/internal/noex.rb +1 -0
- data/lib/internal/obfusc.rb +57 -0
- data/lib/internal/object.rb +1 -0
- data/lib/internal/object/as_code.rb +10 -0
- data/lib/internal/proc.rb +1 -0
- data/lib/internal/proc/as_code.rb +21 -0
- data/lib/internal/proc/as_expression.rb +14 -0
- data/lib/internal/proc/signature.rb +184 -0
- data/lib/internal/tag.rb +1 -0
- data/lib/internal/thread.rb +1 -0
- data/lib/internal/vm.rb +1 -0
- data/lib/internal/vm/bytedecoder.rb +866 -0
- data/lib/internal/vm/constants.rb +1 -0
- data/lib/internal/vm/control_frame.rb +1 -0
- data/lib/internal/vm/inline_cache.rb +1 -0
- data/lib/internal/vm/instruction.rb +1 -0
- data/lib/internal/vm/iseq.rb +1 -0
- data/lib/internal/vm/iseq/as_code.rb +27 -0
- data/lib/internal/vm/iseq/as_expression.rb +26 -0
- data/metaconfig +19 -0
- data/post-config.rb +1 -0
- data/post-install.rb +4 -0
- data/post-setup.rb +7 -0
- data/pre-config.rb +96 -0
- data/pre-install.rb +13 -0
- data/pre-setup.rb +8 -0
- data/run_tests.rb +26 -0
- data/setup.rb +1599 -0
- data/test/expression_samples.rb +160 -0
- data/test/node_samples.rb +122 -0
- data/test/test_as_code.rb +261 -0
- data/test/test_as_expression.rb +229 -0
- data/test/test_dump_class.rb +187 -0
- data/test/test_dump_method.rb +144 -0
- data/test/test_dump_proc.rb +118 -0
- data/test/test_helpers.rb +61 -0
- data/test/test_method.rb +72 -0
- data/test/test_methodsig.rb +267 -0
- data/test/test_module.rb +49 -0
- data/test/test_node.rb +77 -0
- data/test/test_proc.rb +47 -0
- metadata +377 -0
data/lib/internal/tag.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'internal/tag/tag'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'internal/thread/thread'
|
data/lib/internal/vm.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'internal/vm/vm'
|
|
@@ -0,0 +1,866 @@
|
|
|
1
|
+
require 'internal/vm/iseq'
|
|
2
|
+
require 'internal/vm/instruction'
|
|
3
|
+
require 'internal/vm/inline_cache'
|
|
4
|
+
require 'internal/vm/constants'
|
|
5
|
+
|
|
6
|
+
module Nodewrap
|
|
7
|
+
|
|
8
|
+
# A module for decoding YARV bytecode.
|
|
9
|
+
#
|
|
10
|
+
# This is actually pretty cool. It's actually a miniature VM, where the
|
|
11
|
+
# result of evaluating an expression is itself another expression. This
|
|
12
|
+
# turns out to be much simpler than a full ruby VM, but I think one
|
|
13
|
+
# could use this as a base for building one.
|
|
14
|
+
#
|
|
15
|
+
# Example usage:
|
|
16
|
+
# env = Nodewrap::ByteDecoder::Environment.new(is.local_table)
|
|
17
|
+
# is = RubyVM::InstructionSequence.new('1 + 1')
|
|
18
|
+
# is.bytedecode(env)
|
|
19
|
+
# env.expressions.each do |expr|
|
|
20
|
+
# puts expr
|
|
21
|
+
# end
|
|
22
|
+
# puts stack[-1]
|
|
23
|
+
#
|
|
24
|
+
module ByteDecoder
|
|
25
|
+
|
|
26
|
+
class Environment
|
|
27
|
+
attr_reader :stack
|
|
28
|
+
attr_reader :expressions
|
|
29
|
+
attr_reader :local_table
|
|
30
|
+
attr_accessor :last
|
|
31
|
+
attr_reader :seq
|
|
32
|
+
attr_accessor :pc
|
|
33
|
+
|
|
34
|
+
def initialize(local_table)
|
|
35
|
+
@stack = []
|
|
36
|
+
@expressions = []
|
|
37
|
+
@local_table = local_table
|
|
38
|
+
@last = nil
|
|
39
|
+
@pc = 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def advance(instruction_length)
|
|
43
|
+
@pc += instruction_length
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def remember(expression)
|
|
47
|
+
if not expression.is_a?(Expression::Literal) then
|
|
48
|
+
@expressions << expression
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Expression
|
|
54
|
+
attr_reader :pc
|
|
55
|
+
|
|
56
|
+
def initialize(pc)
|
|
57
|
+
@pc = pc
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def <=>(rhs)
|
|
61
|
+
return @pc <=> rhs.pc
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def fmt(arg)
|
|
65
|
+
if arg.respond_to?(:precedence)
|
|
66
|
+
p = arg.precedence
|
|
67
|
+
else
|
|
68
|
+
p = 0
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if p >= self.precedence then
|
|
72
|
+
return "(#{arg})"
|
|
73
|
+
else
|
|
74
|
+
return arg
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class Literal < Expression
|
|
79
|
+
attr_reader :value
|
|
80
|
+
|
|
81
|
+
def initialize(pc, value)
|
|
82
|
+
super(pc)
|
|
83
|
+
@value = value
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def to_s
|
|
87
|
+
case @value
|
|
88
|
+
when Regexp then "/#{@value.inspect[1..-2]}/"
|
|
89
|
+
else; return @value.inspect
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def precedence
|
|
94
|
+
return 1
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class Infix < Expression
|
|
99
|
+
attr_reader :op
|
|
100
|
+
attr_reader :lhs
|
|
101
|
+
attr_reader :rhs
|
|
102
|
+
|
|
103
|
+
def initialize(pc, op, lhs, rhs)
|
|
104
|
+
super(pc)
|
|
105
|
+
@op = op
|
|
106
|
+
@lhs = lhs
|
|
107
|
+
@rhs = rhs
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def to_s
|
|
111
|
+
return "#{fmt(@lhs)} #{@op} #{fmt(@rhs)}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def precedence
|
|
115
|
+
case @op
|
|
116
|
+
when :*, :/, :%
|
|
117
|
+
return 2
|
|
118
|
+
when '+'.intern, '-'.intern
|
|
119
|
+
return 3
|
|
120
|
+
when :<<, :>>
|
|
121
|
+
return 4
|
|
122
|
+
when :>, :>=, :<, :<=, :==, :===, :!=
|
|
123
|
+
return 5
|
|
124
|
+
when :undef
|
|
125
|
+
return 6
|
|
126
|
+
else
|
|
127
|
+
raise ArgumentError, "Unknown op: #{@op}"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class Prefix < Expression
|
|
133
|
+
def initialize(pc, op, expr)
|
|
134
|
+
super(pc)
|
|
135
|
+
@op = op
|
|
136
|
+
@expr = expr
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def to_s
|
|
140
|
+
op = @op.to_s
|
|
141
|
+
op.chop! if op[-1] == ?@
|
|
142
|
+
if @op == '!'.intern and @expr.is_a?(Infix) and @expr.op == :== then
|
|
143
|
+
return "#{@expr.fmt(@expr.lhs)} != #{@expr.fmt(@expr.rhs)}"
|
|
144
|
+
elsif self.precedence < @expr.precedence then
|
|
145
|
+
return "#{op}(#{@expr})"
|
|
146
|
+
else
|
|
147
|
+
return "#{op}#{@expr}"
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def precedence
|
|
152
|
+
return 1
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
class Send < Expression
|
|
157
|
+
attr_reader :is_assignment
|
|
158
|
+
|
|
159
|
+
def initialize(pc, id, has_receiver, has_parens, receiver, block, splat_last, *args)
|
|
160
|
+
super(pc)
|
|
161
|
+
@id = id
|
|
162
|
+
@is_assignment = id.to_s[-1] == ?=
|
|
163
|
+
@has_receiver = has_receiver
|
|
164
|
+
@has_parens = has_parens
|
|
165
|
+
@receiver = receiver
|
|
166
|
+
@block = block
|
|
167
|
+
@splat_last = splat_last
|
|
168
|
+
@args = args
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def to_s
|
|
172
|
+
s = ''
|
|
173
|
+
receiver_str = @has_receiver \
|
|
174
|
+
? "#{@receiver}." \
|
|
175
|
+
: nil
|
|
176
|
+
args = @args.map { |x| x.to_s }
|
|
177
|
+
if @splat_last then
|
|
178
|
+
args[-1] = "*#{@args[-1]}"
|
|
179
|
+
end
|
|
180
|
+
if @is_assignment and args.size == 1 then
|
|
181
|
+
s = "#{receiver_str}#{@id.to_s[0..-2]} = #{args[0]}"
|
|
182
|
+
else
|
|
183
|
+
open = @has_parens ? '(' : ''
|
|
184
|
+
close = @has_parens ? ')' : ''
|
|
185
|
+
s = "#{receiver_str}#{@id}#{open}#{args.join(', ')}#{close}"
|
|
186
|
+
end
|
|
187
|
+
if @block then
|
|
188
|
+
# TODO: this code is duplicated elsewhere
|
|
189
|
+
# TODO: handle block args
|
|
190
|
+
env = Environment.new(@block.local_table)
|
|
191
|
+
@block.bytedecode(env)
|
|
192
|
+
expressions = env.expressions + env.stack
|
|
193
|
+
expressions.sort!
|
|
194
|
+
expressions.map! { |x| x.to_s }
|
|
195
|
+
if expressions.length == 1 and
|
|
196
|
+
expressions[0].is_a?(Literal) and
|
|
197
|
+
expressions[0].value == nil then
|
|
198
|
+
# empty
|
|
199
|
+
else
|
|
200
|
+
s << " { #{expressions.join('; ')} }"
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
return s
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def precedence
|
|
207
|
+
if @has_receiver then
|
|
208
|
+
if @receiver.respond_to?(:precedence) then
|
|
209
|
+
return @receiver.precedence
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
return 1
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
class Self < Expression
|
|
217
|
+
def initialize(pc)
|
|
218
|
+
super(pc)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def to_s
|
|
222
|
+
return "self"
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def precedence
|
|
226
|
+
return 1
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
class Hash < Expression
|
|
231
|
+
def initialize(pc, args)
|
|
232
|
+
super(pc)
|
|
233
|
+
@args = args
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def to_s
|
|
237
|
+
s = '{ '
|
|
238
|
+
a = []
|
|
239
|
+
i = 0
|
|
240
|
+
while i < @args.length do
|
|
241
|
+
a << "#{@args[i]} => #{@args[i + 1]}"
|
|
242
|
+
i += 2
|
|
243
|
+
end
|
|
244
|
+
s << a.join(', ')
|
|
245
|
+
s << ' ' if a.length != 0
|
|
246
|
+
s << '}'
|
|
247
|
+
return s
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def precedence
|
|
251
|
+
return 1
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
class Array < Expression
|
|
256
|
+
def initialize(pc, args)
|
|
257
|
+
super(pc)
|
|
258
|
+
@args = args
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def to_s
|
|
262
|
+
s = '[ '
|
|
263
|
+
s << @args.join(', ')
|
|
264
|
+
s << ' ]'
|
|
265
|
+
return s
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def precedence
|
|
269
|
+
return 1
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
class ConcatArray < Expression
|
|
274
|
+
def initialize(array, splat)
|
|
275
|
+
@array = array
|
|
276
|
+
@splat = splat
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def to_s
|
|
280
|
+
s = '[ '
|
|
281
|
+
case @array
|
|
282
|
+
when Array then s << @array.args.join(', ')
|
|
283
|
+
when Literal then s << @array.value.join(', ')
|
|
284
|
+
else; raise "Unexpected: #{@array.inspect}"
|
|
285
|
+
end
|
|
286
|
+
s << ', *'
|
|
287
|
+
s << @splat.to_s
|
|
288
|
+
s << ' ]'
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def precedence
|
|
292
|
+
return 1
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
class Defined < Expression
|
|
297
|
+
def initialize(pc, arg)
|
|
298
|
+
super(pc)
|
|
299
|
+
@arg = arg
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def to_s
|
|
303
|
+
return "defined?(#{@arg.to_s})"
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def precedence
|
|
307
|
+
return 1
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
class Variable < Expression
|
|
312
|
+
def initialize(pc, name)
|
|
313
|
+
super(pc)
|
|
314
|
+
@name = name
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def to_s
|
|
318
|
+
return @name.to_s
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def precedence
|
|
322
|
+
return 1
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
class Constant < Expression
|
|
327
|
+
def initialize(pc, klass, name)
|
|
328
|
+
super(pc)
|
|
329
|
+
@klass = klass
|
|
330
|
+
@name = name
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def to_s
|
|
334
|
+
if @klass then
|
|
335
|
+
if @klass == Object then
|
|
336
|
+
return "::#{@name}"
|
|
337
|
+
else
|
|
338
|
+
return "#{@klass}::#{@name}"
|
|
339
|
+
end
|
|
340
|
+
else
|
|
341
|
+
return "#{@name}"
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def precedence
|
|
346
|
+
return 1
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
class ConstantAssignment < Constant
|
|
351
|
+
def initialize(pc, klass, name, value)
|
|
352
|
+
super(pc, klass, name)
|
|
353
|
+
@value = value
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def to_s
|
|
357
|
+
s = super()
|
|
358
|
+
s << " = #{@value}"
|
|
359
|
+
return s
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
class ConcatStrings < Expression
|
|
364
|
+
def initialize(pc, args)
|
|
365
|
+
super(pc)
|
|
366
|
+
@args = args
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def to_s
|
|
370
|
+
s = "\""
|
|
371
|
+
@args.each do |arg|
|
|
372
|
+
case arg
|
|
373
|
+
when Literal
|
|
374
|
+
case arg.value
|
|
375
|
+
when String then s << arg.value
|
|
376
|
+
else; s << arg.to_s
|
|
377
|
+
end
|
|
378
|
+
else
|
|
379
|
+
s << "\#{#{arg.to_s}}"
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
s << "\""
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def precedence
|
|
386
|
+
return 1
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
class Assignment < Expression
|
|
391
|
+
attr_reader :rhs
|
|
392
|
+
|
|
393
|
+
def initialize(pc, name, rhs)
|
|
394
|
+
super(pc)
|
|
395
|
+
@name = name
|
|
396
|
+
@rhs = rhs
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def to_s
|
|
400
|
+
return "#{@name} = #{@rhs}"
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def precedence
|
|
404
|
+
return 5
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
class ToRegexp < Expression
|
|
409
|
+
def initialize(pc, value)
|
|
410
|
+
super(pc)
|
|
411
|
+
@value = value
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def to_s
|
|
415
|
+
case @value
|
|
416
|
+
when ConcatStrings
|
|
417
|
+
string = @value.to_s
|
|
418
|
+
unstring = string[1..-2]
|
|
419
|
+
return Regexp.compile(unstring).inspect
|
|
420
|
+
else
|
|
421
|
+
return Regexp.compile(@value.to_s).inspect
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def precedence
|
|
426
|
+
return 1
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
class Throw < Expression
|
|
431
|
+
def initialize(pc, value)
|
|
432
|
+
super(pc)
|
|
433
|
+
@value = value
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def to_s
|
|
437
|
+
# TODO: not all throws are breaks...
|
|
438
|
+
if not @value or (@value.is_a?(Literal) and @value.value == nil) then
|
|
439
|
+
return "break"
|
|
440
|
+
else
|
|
441
|
+
return "break #{@value}"
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def precedence
|
|
446
|
+
return 1
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
end # ByteDecoder
|
|
452
|
+
|
|
453
|
+
end # Nodewrap
|
|
454
|
+
|
|
455
|
+
class RubyVM
|
|
456
|
+
class Instruction
|
|
457
|
+
include Nodewrap::ByteDecoder
|
|
458
|
+
|
|
459
|
+
class PUTOBJECT
|
|
460
|
+
def bytedecode(env)
|
|
461
|
+
env.stack.push Expression::Literal.new(env.pc, self.operands[0])
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
INFIX_OPCODES = {
|
|
466
|
+
OPT_PLUS => '+'.intern,
|
|
467
|
+
OPT_MINUS => '-'.intern,
|
|
468
|
+
OPT_MULT => :*,
|
|
469
|
+
OPT_DIV => :/,
|
|
470
|
+
OPT_MOD => :%,
|
|
471
|
+
OPT_LTLT => :<<,
|
|
472
|
+
# OPT_GTGT => :>>,
|
|
473
|
+
OPT_EQ => :==,
|
|
474
|
+
OPT_NEQ => :!=,
|
|
475
|
+
OPT_GT => :>,
|
|
476
|
+
OPT_GE => :>=,
|
|
477
|
+
OPT_LT => :<,
|
|
478
|
+
OPT_LE => :<=,
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
INFIX_OPERATORS = INFIX_OPCODES.values + [ :===, :>> ]
|
|
482
|
+
|
|
483
|
+
INFIX_OPCODES.each do |klass, op|
|
|
484
|
+
klass.class_eval do
|
|
485
|
+
define_method(:bytedecode) do |env|
|
|
486
|
+
rhs = env.stack.pop
|
|
487
|
+
lhs = env.stack.pop
|
|
488
|
+
env.stack.push Expression::Infix.new(env.pc, op, lhs, rhs)
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
PREFIX_OPCODES = {
|
|
494
|
+
OPT_NOT => :!,
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if defined?(UNDEF)
|
|
498
|
+
PREFIX_OPCODES[UNDEF] = :undef
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
PREFIX_OPERATORS = PREFIX_OPCODES.values + [ :~, :+@, :-@ ]
|
|
502
|
+
|
|
503
|
+
PREFIX_OPCODES.each do |klass, op|
|
|
504
|
+
klass.class_eval do
|
|
505
|
+
define_method(:bytedecode) do |env|
|
|
506
|
+
expr = env.stack.pop
|
|
507
|
+
env.stack.push Expression::Prefix.new(env.pc, op, expr)
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
class TRACE
|
|
513
|
+
def bytedecode(env)
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
class LEAVE
|
|
518
|
+
def bytedecode(env)
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
LITERAL_OPCODES = [
|
|
523
|
+
PUTNIL,
|
|
524
|
+
DUPARRAY,
|
|
525
|
+
PUTSTRING,
|
|
526
|
+
]
|
|
527
|
+
|
|
528
|
+
LITERAL_OPCODES.each do |klass|
|
|
529
|
+
klass.class_eval do
|
|
530
|
+
define_method(:bytedecode) do |env|
|
|
531
|
+
env.stack.push Expression::Literal.new(env.pc, @operands[0])
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
class SEND
|
|
537
|
+
def bytedecode(env)
|
|
538
|
+
id = @operands[0]
|
|
539
|
+
num_args = @operands[1]
|
|
540
|
+
args = []
|
|
541
|
+
num_args.times do
|
|
542
|
+
args.unshift env.stack.pop
|
|
543
|
+
end
|
|
544
|
+
has_receiver = !flag_set(RubyVM::CALL_FCALL_BIT)
|
|
545
|
+
has_parens = !flag_set(RubyVM::CALL_VCALL_BIT)
|
|
546
|
+
splat_last = flag_set(RubyVM::CALL_ARGS_SPLAT_BIT)
|
|
547
|
+
receiver = env.stack.pop
|
|
548
|
+
block = @operands[2]
|
|
549
|
+
if INFIX_OPERATORS.include?(id) and args.size == 1 then
|
|
550
|
+
env.stack.push Expression::Infix.new(env.pc, id, receiver, args[0])
|
|
551
|
+
elsif PREFIX_OPERATORS.include?(id) and args.size == 0 then
|
|
552
|
+
env.stack.push Expression::Prefix.new(env.pc, id, receiver)
|
|
553
|
+
else
|
|
554
|
+
env.stack.push Expression::Send.new(
|
|
555
|
+
env.pc, id, has_receiver, has_parens, receiver, block, splat_last, *args)
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def flag_set(flag)
|
|
560
|
+
flags = @operands[3]
|
|
561
|
+
return flags & flag == flag
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
class PUTSELF
|
|
566
|
+
def bytedecode(env)
|
|
567
|
+
env.stack.push Expression::Self.new(env.pc)
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
class NEWHASH
|
|
572
|
+
def bytedecode(env)
|
|
573
|
+
i = @operands[0]
|
|
574
|
+
args = []
|
|
575
|
+
while i > 0 do
|
|
576
|
+
args.unshift env.stack.pop
|
|
577
|
+
i -= 1
|
|
578
|
+
end
|
|
579
|
+
env.stack.push Expression::Hash.new(env.pc, args)
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
class NEWARRAY
|
|
584
|
+
def bytedecode(env)
|
|
585
|
+
i = @operands[0]
|
|
586
|
+
args = []
|
|
587
|
+
while i > 0 do
|
|
588
|
+
args.unshift env.stack.pop
|
|
589
|
+
i -= 1
|
|
590
|
+
end
|
|
591
|
+
env.stack.push Expression::Array.new(env.pc, args)
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
class DEFINED
|
|
596
|
+
def bytedecode(env)
|
|
597
|
+
env.stack.push Expression::Defined.new(env.pc, @operands[1])
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
GET_VARIABLE_OPCODES = [
|
|
602
|
+
GETCLASSVARIABLE,
|
|
603
|
+
GETINSTANCEVARIABLE,
|
|
604
|
+
GETGLOBAL,
|
|
605
|
+
]
|
|
606
|
+
|
|
607
|
+
GET_VARIABLE_OPCODES.each do |klass|
|
|
608
|
+
klass.class_eval do
|
|
609
|
+
define_method(:bytedecode) do |env|
|
|
610
|
+
env.stack.push Expression::Variable.new(env.pc, @operands[0])
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
SET_VARIABLE_OPCODES = [
|
|
616
|
+
SETCLASSVARIABLE,
|
|
617
|
+
SETINSTANCEVARIABLE,
|
|
618
|
+
SETGLOBAL,
|
|
619
|
+
]
|
|
620
|
+
|
|
621
|
+
SET_VARIABLE_OPCODES.each do |klass|
|
|
622
|
+
klass.class_eval do
|
|
623
|
+
define_method(:bytedecode) do |env|
|
|
624
|
+
value = env.stack.pop
|
|
625
|
+
env.stack.delete_at(-1) # TODO: dup'd value.. is this right?
|
|
626
|
+
env.stack.push Expression::Assignment.new(env.pc, @operands[0], value)
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
class GETCONSTANT
|
|
632
|
+
def bytedecode(env)
|
|
633
|
+
klass = env.stack.pop
|
|
634
|
+
env.stack.push Expression::Constant.new(env.pc, klass, @operands[0])
|
|
635
|
+
end
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
class SETCONSTANT
|
|
639
|
+
def bytedecode(env)
|
|
640
|
+
klass = env.stack.pop
|
|
641
|
+
value = env.stack.pop
|
|
642
|
+
env.stack.push Expression::ConstantAssignment.new(env.pc, klass, @operands[0], value)
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
class GETSPECIAL
|
|
647
|
+
def bytedecode(env)
|
|
648
|
+
type = @operands[1] >> 1
|
|
649
|
+
type += ?0.ord if type < 10
|
|
650
|
+
env.stack.push Expression::Variable.new(env.pc, "$#{type.chr}")
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
class GETINLINECACHE
|
|
655
|
+
def bytedecode(env)
|
|
656
|
+
env.stack.push nil
|
|
657
|
+
end
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
class SETINLINECACHE
|
|
661
|
+
def bytedecode(env)
|
|
662
|
+
end
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
class NOP
|
|
666
|
+
def bytedecode(env)
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
class TOSTRING
|
|
671
|
+
def bytedecode(env)
|
|
672
|
+
end
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
class CONCATSTRINGS
|
|
676
|
+
def bytedecode(env)
|
|
677
|
+
i = @operands[0]
|
|
678
|
+
args = []
|
|
679
|
+
while i > 0 do
|
|
680
|
+
args.unshift env.stack.pop
|
|
681
|
+
i -= 1
|
|
682
|
+
end
|
|
683
|
+
env.stack.push Expression::ConcatStrings.new(env.pc, args)
|
|
684
|
+
end
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
class TOREGEXP
|
|
688
|
+
def bytedecode(env)
|
|
689
|
+
env.stack.push Expression::ToRegexp.new(env.pc, env.stack.pop)
|
|
690
|
+
end
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
class DUP
|
|
694
|
+
def bytedecode(env)
|
|
695
|
+
arg = env.stack.pop
|
|
696
|
+
env.stack.push arg
|
|
697
|
+
env.stack.push arg
|
|
698
|
+
end
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
class SETLOCAL
|
|
702
|
+
def bytedecode(env)
|
|
703
|
+
idx = env.local_table.size - @operands[0] + 1
|
|
704
|
+
name = env.local_table[idx]
|
|
705
|
+
value = env.stack.pop
|
|
706
|
+
env.stack.push Expression::Assignment.new(env.pc, name, value)
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
class GETLOCAL
|
|
711
|
+
def bytedecode(env)
|
|
712
|
+
idx = env.local_table.size - @operands[0] + 1
|
|
713
|
+
name = env.local_table[idx]
|
|
714
|
+
env.stack.push Expression::Variable.new(env.pc, name)
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
class SETDYNAMIC
|
|
719
|
+
def bytedecode(env)
|
|
720
|
+
idx = env.local_table.size - @operands[0]
|
|
721
|
+
name = env.local_table[idx]
|
|
722
|
+
value = env.stack.pop
|
|
723
|
+
env.stack.push Expression::Assignment.new(env.pc, name, value)
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
class GETDYNAMIC
|
|
728
|
+
def bytedecode(env)
|
|
729
|
+
idx = env.local_table.size - @operands[0]
|
|
730
|
+
name = env.local_table[idx]
|
|
731
|
+
env.stack.push Expression::Variable.new(env.pc, name)
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
class SETN
|
|
736
|
+
# set nth stack entry to stack top
|
|
737
|
+
def bytedecode(env)
|
|
738
|
+
n = @operands[0]
|
|
739
|
+
dest = -(n+1)
|
|
740
|
+
if env.stack[dest].is_a?(Expression) then
|
|
741
|
+
env.remember env.stack[dest]
|
|
742
|
+
end
|
|
743
|
+
env.stack[dest] = env.stack[-1]
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
class TOPN
|
|
748
|
+
# get nth stack entry from stack top
|
|
749
|
+
def bytedecode(env)
|
|
750
|
+
n = @operands[0]
|
|
751
|
+
idx = -(n+1)
|
|
752
|
+
env.stack[idx]
|
|
753
|
+
end
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
class POP
|
|
757
|
+
def bytedecode(env)
|
|
758
|
+
top = env.stack[-1]
|
|
759
|
+
if top.is_a?(Expression::Send) and top.is_assignment then
|
|
760
|
+
# special case - the return value from the assignment gets
|
|
761
|
+
# thrown away and the result is the rhs
|
|
762
|
+
env.remember env.stack[-2]
|
|
763
|
+
env.stack.delete_at(-2)
|
|
764
|
+
end
|
|
765
|
+
env.remember top
|
|
766
|
+
env.stack.pop
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
class THROW
|
|
771
|
+
def bytedecode(env)
|
|
772
|
+
value = env.stack.pop
|
|
773
|
+
env.remember env.stack.pop
|
|
774
|
+
env.stack.push Expression::Throw.new(env.pc, value)
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
class CONCATARRAY
|
|
779
|
+
def bytedecode(env)
|
|
780
|
+
splat = env.stack.pop
|
|
781
|
+
array = env.stack.pop
|
|
782
|
+
env.stack.push Expression::ConcatArray.new(array, splat)
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
class InstructionSequence
|
|
788
|
+
def bytedecode(env, start_pc=0, end_pc=nil, &block)
|
|
789
|
+
self.each(start_pc) do |instruction|
|
|
790
|
+
# p instruction
|
|
791
|
+
instruction.bytedecode(env)
|
|
792
|
+
# p env.stack
|
|
793
|
+
env.advance(instruction.length)
|
|
794
|
+
break if end_pc and env.pc >= end_pc
|
|
795
|
+
break if block and block.call(instruction)
|
|
796
|
+
end
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
def opt_pc
|
|
800
|
+
opt_table = self.arg_opt_table
|
|
801
|
+
return opt_table.length > 0 ? opt_table[-1] : 0
|
|
802
|
+
end
|
|
803
|
+
end
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
if __FILE__ == $0 then
|
|
807
|
+
# def foo; @@foo = 1; end
|
|
808
|
+
# def foo; a = [2, 3]; foo(1, *a); end
|
|
809
|
+
# def foo; not true; end
|
|
810
|
+
# def foo; catch(:foo) { throw :foo; 42 }; end
|
|
811
|
+
# def foo; a ? b : c; end
|
|
812
|
+
# def foo; loop { a = 1; break }; end
|
|
813
|
+
# def foo; ::BAR; end
|
|
814
|
+
# def foo; a != b; end
|
|
815
|
+
# def foo; 1 - 2; end
|
|
816
|
+
# def foo; +a; end
|
|
817
|
+
# def foo; !a; end
|
|
818
|
+
# def foo; a << b; end
|
|
819
|
+
# def foo; a === b; end
|
|
820
|
+
# def foo; []; end
|
|
821
|
+
def foo; foo.bar = 42; end
|
|
822
|
+
# def foo; h = {}; h.default = true; h; end
|
|
823
|
+
# def foo; @FOO; end
|
|
824
|
+
# def foo; $FOO; end
|
|
825
|
+
# def foo; /foo#{bar}/; end
|
|
826
|
+
# def foo; /foo/; end
|
|
827
|
+
# def foo; foo = 1; bar=2; baz=3 end
|
|
828
|
+
# def foo; "foo#{bar}"; end
|
|
829
|
+
# def foo; $`; end
|
|
830
|
+
# def foo; FOO; end
|
|
831
|
+
# def foo; @@foo; end
|
|
832
|
+
# def foo; defined?(FOO); end
|
|
833
|
+
# def foo; [1+1, 2, 3, 4] ; end
|
|
834
|
+
# def foo; { 1 => 2, 3 => 4 }; end
|
|
835
|
+
# def foo; foo(1 + 2 * (3 + 4), 5); end
|
|
836
|
+
# def foo; 1 + 2 * (3 + 4); end
|
|
837
|
+
|
|
838
|
+
n = method(:foo).body
|
|
839
|
+
is = n.body
|
|
840
|
+
puts is.disasm
|
|
841
|
+
|
|
842
|
+
env = Nodewrap::ByteDecoder::Environment.new(is.local_table)
|
|
843
|
+
s = ''
|
|
844
|
+
# puts "local_table = #{is.local_table.inspect}"
|
|
845
|
+
is.each do |i|
|
|
846
|
+
# p i.operand_types, i.operand_names
|
|
847
|
+
# p i #, i.operand_types, i.operand_names
|
|
848
|
+
print i.class, ' '
|
|
849
|
+
a = []
|
|
850
|
+
i.operand_names.each_with_index do |name, idx|
|
|
851
|
+
a << "#{name}(#{i.operand_types[idx]})=#{i.operands[idx].inspect}"
|
|
852
|
+
end
|
|
853
|
+
puts a.join(', ')
|
|
854
|
+
i.bytedecode(env)
|
|
855
|
+
env.advance(i.length)
|
|
856
|
+
# p env.stack
|
|
857
|
+
# p env.stack.map { |x| x.to_s }
|
|
858
|
+
# puts
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
puts "---"
|
|
862
|
+
(env.expressions + env.stack).sort.each do |expr|
|
|
863
|
+
puts expr.to_s
|
|
864
|
+
end
|
|
865
|
+
end
|
|
866
|
+
|