/usr/lib/ruby/vendor_ruby/temple/mixins/dispatcher.rb is in ruby-temple 0.6.7-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | module Temple
module Mixins
# @api private
module CoreDispatcher
def on_multi(*exps)
multi = [:multi]
exps.each {|exp| multi << compile(exp) }
multi
end
def on_capture(name, exp)
[:capture, name, compile(exp)]
end
end
# @api private
module EscapeDispatcher
def on_escape(flag, exp)
[:escape, flag, compile(exp)]
end
end
# @api private
module ControlFlowDispatcher
def on_if(condition, *cases)
[:if, condition, *cases.compact.map {|e| compile(e) }]
end
def on_case(arg, *cases)
[:case, arg, *cases.map {|condition, exp| [condition, compile(exp)] }]
end
def on_block(code, content)
[:block, code, compile(content)]
end
def on_cond(*cases)
[:cond, *cases.map {|condition, exp| [condition, compile(exp)] }]
end
end
# @api private
module CompiledDispatcher
def call(exp)
compile(exp)
end
def compile(exp)
dispatcher(exp)
end
private
def dispatcher(exp)
replace_dispatcher(exp)
end
def replace_dispatcher(exp)
tree = DispatchNode.new
dispatched_methods.each do |method|
method.split('_')[1..-1].inject(tree) {|node, type| node[type.to_sym] }.method = method
end
self.class.class_eval %{def dispatcher(exp)
return replace_dispatcher(exp) if self.class != #{self.class}
#{tree.compile.gsub("\n", "\n ")}
end}
dispatcher(exp)
end
def dispatched_methods
re = /^on(_[a-zA-Z0-9]+)*$/
self.methods.map(&:to_s).select(&re.method(:=~))
end
# @api private
class DispatchNode < Hash
attr_accessor :method
def initialize
super { |hsh,key| hsh[key] = DispatchNode.new }
@method = nil
end
def compile(level = 0, call_parent = nil)
call_method = method ? (level == 0 ? "#{method}(*exp)" :
"#{method}(*exp[#{level}..-1])") : call_parent
if empty?
raise 'Invalid dispatcher node' unless method
call_method
else
code = "case(exp[#{level}])\n"
each do |key, child|
code << "when #{key.inspect}\n " <<
child.compile(level + 1, call_method).gsub("\n", "\n ") << "\n"
end
code << "else\n " << (call_method || 'exp') << "\nend"
end
end
end
end
# @api public
#
# Implements a compatible call-method
# based on the including classe's methods.
#
# It uses every method starting with
# "on" and uses the rest of the method
# name as prefix of the expression it
# will receive. So, if a dispatcher
# has a method named "on_x", this method
# will be called with arg0,..,argN
# whenever an expression like [:x, arg0,..,argN ]
# is encountered.
#
# This works with longer prefixes, too.
# For example a method named "on_y_z"
# will be called whenever an expression
# like [:y, :z, .. ] is found. Furthermore,
# if additionally a method named "on_y"
# is present, it will be called when an
# expression starts with :y but then does
# not contain with :z. This way a
# dispatcher can implement namespaces.
#
# @note
# Processing does not reach into unknown
# expression types by default.
#
# @example
# class MyAwesomeDispatch
# include Temple::Mixins::Dispatcher
# def on_awesome(thing) # keep awesome things
# return [:awesome, thing]
# end
# def on_boring(thing) # make boring things awesome
# return [:awesome, thing+" with bacon"]
# end
# def on(type,*args) # unknown stuff is boring too
# return [:awesome, 'just bacon']
# end
# end
# filter = MyAwesomeDispatch.new
# # Boring things are converted:
# filter.call([:boring, 'egg']) #=> [:awesome, 'egg with bacon']
# # Unknown things too:
# filter.call([:foo]) #=> [:awesome, 'just bacon']
# # Known but not boring things won't be touched:
# filter.call([:awesome, 'chuck norris']) #=>[:awesome, 'chuck norris']
#
module Dispatcher
include CompiledDispatcher
include CoreDispatcher
include EscapeDispatcher
include ControlFlowDispatcher
end
end
end
|