module Temple::Mixins::EngineDSL

def chain_proc_constructor(name, filter)

def chain_proc_constructor(name, filter)
  raise(ArgumentError, 'Proc or blocks must have arity 0 or 1') if filter.arity > 1
  method_name = "FILTER #{name}"
  c = Class === self ? self : singleton_class
  filter = c.class_eval { define_method(method_name, &filter); instance_method(method_name) }
  proc do |engine|
    if filter.arity == 1
      # the proc takes one argument, e.g. use(:Filter) {|exp| exp }
      filter.bind(engine)
    else
      f = filter.bind(engine).call
      if f.respond_to? :call
        # the proc returns a callable object, e.g. use(:Filter) { Filter.new }
        f
      else
        raise(ArgumentError, 'Proc or blocks must return a Callable or a Class') unless f.respond_to? :new
        # the proc returns a class, e.g. use(:Filter) { Filter }
        f.new(f.respond_to?(:options) ? engine.options.to_hash.select {|k,v| f.options.valid_key?(k) } : engine.options)
      end
    end
  end
end