Last active
October 18, 2017 21:32
-
-
Save Heimdell/699e525e18f0058f4d6189e778dc9d63 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| I want to store some call tree, like | |
| > push 1 | |
| > seq do | |
| > dup | |
| > push 1 | |
| > drop | |
| > end | |
| > swap | |
| ... and then unleash it on some object. | |
| Notice, that call results are ignored, | |
| since in the end I'm only interested in side-effects. | |
| """ | |
| """ | |
| This object stores any call tree invoked on it. | |
| """ | |
| class Catcher | |
| def initialize | |
| @context = [[]] | |
| end | |
| def method_missing name, *args | |
| if block_given? then | |
| @context.push [] | |
| yield | |
| chain = @context.pop | |
| @context.last.push name: name, args: args, do: chain | |
| else | |
| @context.last.push name: name, args: args | |
| end | |
| end | |
| end | |
| """ | |
| This method will invoke some call tree on the Catcher | |
| and return what got stored. | |
| """ | |
| def callTree &block | |
| catcher = Catcher.new | |
| catcher.instance_eval &block | |
| catcher.instance_eval do | |
| @context.last | |
| end | |
| end | |
| """ | |
| This method will replay call tree on the object it is invoked on. | |
| """ | |
| def callTheTree tree | |
| this = self | |
| tree.each do |node| | |
| this.instance_eval do | |
| if node[:do] then | |
| this.send node[:name], node[:args] do | |
| callTheTree node[:do] | |
| end | |
| else | |
| this.send node[:name], node[:args] | |
| end | |
| end | |
| end | |
| end | |
| """ | |
| This is a test object that just yells any message sent to it into the console. | |
| """ | |
| class Yeller | |
| def method_missing name, args, &block | |
| # TODO: replace HAX with proper thingies | |
| # NOTICE: begin super.[name](args, &block); rescue e; ...; end | |
| # doesn't work, it just hangs in a loop | |
| return super.send name, args, &block if name == :callTheTree | |
| @indent ||= 0 | |
| put "#{name}(#{args.join ", "})" | |
| if block_given? then | |
| put "{" | |
| @indent += 1 | |
| yield | |
| @indent -= 1 | |
| put "}" | |
| end | |
| end | |
| def put thing | |
| puts (" " * @indent + thing.to_s) | |
| end | |
| end | |
| # dig the tree out | |
| tree = callTree do | |
| seq do | |
| dup | |
| push 1 | |
| par do | |
| seq do | |
| dup | |
| drop | |
| end | |
| drop | |
| end | |
| end | |
| end | |
| # plant the tree to the yelling land | |
| Yeller.new.instance_eval do | |
| callTheTree tree | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment