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
|
# frozen_string_literal: true
module Temple
# An engine is simply a chain of compilers (that often includes a parser,
# some filters and a generator).
#
# class MyEngine < Temple::Engine
# # First run MyParser, passing the :strict option
# use MyParser, :strict
#
# # Then a custom filter
# use MyFilter
#
# # Then some general optimizations filters
# filter :MultiFlattener
# filter :StaticMerger
# filter :DynamicInliner
#
# # Finally the generator
# generator :ArrayBuffer, :buffer
# end
#
# class SpecialEngine < MyEngine
# append MyCodeOptimizer
# before :ArrayBuffer, Temple::Filters::Validator
# replace :ArrayBuffer, Temple::Generators::RailsOutputBuffer
# end
#
# engine = MyEngine.new(strict: "For MyParser")
# engine.call(something)
#
# @api public
class Engine
include Mixins::Options
include Mixins::EngineDSL
extend Mixins::EngineDSL
define_options :file, :streaming, :buffer, :save_buffer
attr_reader :chain
def self.chain
@chain ||= superclass.respond_to?(:chain) ? superclass.chain.dup : []
end
def initialize(opts = {})
super
@chain = self.class.chain.dup
end
def call(input)
call_chain.inject(input) {|m, e| e.call(m) }
end
protected
def chain_modified!
@call_chain = nil
end
def call_chain
@call_chain ||= @chain.map do |name, constructor|
f = constructor.call(self)
raise "Constructor #{name} must return callable object" if f && !f.respond_to?(:call)
f
end.compact
end
end
end
|