Class: Babl::Builder::ChainBuilder
- Inherits:
-
Object
- Object
- Babl::Builder::ChainBuilder
- Defined in:
- lib/babl/builder/chain_builder.rb
Overview
Builder provides a simple framework for defining & chaining BABL’s operators easily.
Compiling a template is a multi-phase process:
1- [BABL => ChainBuilder] Template definition (via Builder#construct_node & Builder#construct_terminal) :
The operator chain is created by wrapping blocks (current block stored in 'scope')
2- [Builder => BoundOperator] Template binding (via Builder#bind) :
A BoundOperator is created for each operator and passed to the next, in left-to-right
order. This step is necessary to propagate context from root to leaves. A typical
use-case is the 'enter' operator, which requires the parent context in which it is called.
3- [BoundOperator => Node] Node precompilation (via Builder#precompile):
BoundOperators are transformed into a Node tree, in right-to-left order. Each node
contains its own rendering logic, dependency tracking & documentation generator.
4- [Node => CompiledTemplate] Compilation output: (via Template#compile):
The resulting Node is used to compute the dependencies & generate the documentation.
Finally, we pack everything is a CompiledTemplate which is exposed to the user.
Instance Method Summary collapse
- #bind(bound) ⇒ Object
- #construct_context ⇒ Object
-
#construct_node ⇒ Object
Append an operator to the chain, and return a new Builder object.
-
#construct_terminal ⇒ Object
Append a terminal operator, and return a new Builder object.
-
#initialize(&block) ⇒ ChainBuilder
constructor
A new instance of ChainBuilder.
- #precompile(node, context) ⇒ Object
- #wrap ⇒ Object
Constructor Details
#initialize(&block) ⇒ ChainBuilder
Returns a new instance of ChainBuilder.
28 29 30 |
# File 'lib/babl/builder/chain_builder.rb', line 28 def initialize(&block) @scope = block end |
Instance Method Details
#bind(bound) ⇒ Object
36 37 38 |
# File 'lib/babl/builder/chain_builder.rb', line 36 def bind(bound) @scope[bound] end |
#construct_context ⇒ Object
58 59 60 61 62 63 64 65 |
# File 'lib/babl/builder/chain_builder.rb', line 58 def construct_context wrap { |bound| new_context = yield(bound.context) next bound if bound.context.equal?(new_context) BoundOperator.new(new_context, &bound.scope) } end |
#construct_node ⇒ Object
Append an operator to the chain, and return a new Builder object
52 53 54 55 56 |
# File 'lib/babl/builder/chain_builder.rb', line 52 def construct_node wrap { |bound| BoundOperator.new(bound.context) { |node| bound.scope[yield(node, bound.context)] } } end |
#construct_terminal ⇒ Object
Append a terminal operator, and return a new Builder object
41 42 43 44 45 46 47 48 49 |
# File 'lib/babl/builder/chain_builder.rb', line 41 def construct_terminal construct_node do |node, context| unless [Nodes::InternalValue.instance, Nodes::TerminalValue.instance].include?(node) raise Errors::InvalidTemplate, 'Chaining is not allowed after a terminal operator' end yield context end end |
#precompile(node, context) ⇒ Object
32 33 34 |
# File 'lib/babl/builder/chain_builder.rb', line 32 def precompile(node, context) bind(BoundOperator.new(context, &:itself)).scope.call(node) end |
#wrap ⇒ Object
67 68 69 |
# File 'lib/babl/builder/chain_builder.rb', line 67 def wrap ChainBuilder.new { |bound| yield bind(bound) } end |