Class: Tipi::Configuration::Assembler

Inherits:
Object
  • Object
show all
Defined in:
lib/tipi/config_dsl.rb

Constant Summary collapse

@@indents =
Hash.new { |h, k| h[k] =  '  ' * k }

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_source(code) ⇒ Object



30
31
32
# File 'lib/tipi/config_dsl.rb', line 30

def self.from_source(code)
  new.from_source code
end

Instance Method Details

#add_app_proc(proc) ⇒ Object



91
92
93
94
95
# File 'lib/tipi/config_dsl.rb', line 91

def add_app_proc(proc)
  id = :"proc#{@app_procs.size}"
  @app_procs[id] = proc
  id
end

#add_frame(&block) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/tipi/config_dsl.rb', line 55

def add_frame(&block)
  @stack.push new_frame
  yield
ensure
  frame = @stack.pop
  emit assemble(frame)
end

#assemble_app_proc(frame) ⇒ Object



115
116
117
118
119
120
121
122
123
124
# File 'lib/tipi/config_dsl.rb', line 115

def assemble_app_proc(frame)
  indent = 0
  lines = []
  emit_code lines, frame[:prelude], indent
  emit_code lines, 'proc do |req|', indent
  emit_code lines, frame[:body], indent + 1
  emit_code lines, 'end', indent

  lines
end

#assemble_frame(frame) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/tipi/config_dsl.rb', line 97

def assemble_frame(frame)
  indent = 0
  lines = []
  emit_code lines, frame[:prelude], indent
  if frame[:rescue_proc_id]
    emit_code lines, 'begin', indent
    indent += 1
  end
  emit_code lines, frame[:body], indent
  if frame[:rescue_proc_id]
    emit_code lines, 'rescue => e', indent
    emit_code lines, "  app_procs[#{frame[:rescue_proc_id].inspect}].call(req, e)", indent
    emit_code lines, 'end', indent
    indent -= 1
  end
  lines
end

#emit(code) ⇒ Object



71
72
73
# File 'lib/tipi/config_dsl.rb', line 71

def emit(code)
  @stack.last[:body] << code
end

#emit_block(conditional, &block) ⇒ Object



84
85
86
87
88
89
# File 'lib/tipi/config_dsl.rb', line 84

def emit_block(conditional, &block)
  proc_id = add_app_proc block
  @stack.last[:branched] = true
  emit conditional
  add_frame &block
end

#emit_code(lines, code, indent) ⇒ Object



126
127
128
129
130
131
132
# File 'lib/tipi/config_dsl.rb', line 126

def emit_code(lines, code, indent)
  if code.is_a? Array
    code.each { |l| emit_code lines, l, indent + 1 }
  else
    lines << (indent_line code, indent)
  end
end

#emit_exception_handler(&block) ⇒ Object



79
80
81
82
# File 'lib/tipi/config_dsl.rb', line 79

def emit_exception_handler(&block)
  proc_id = add_app_proc block
  @stack.last[:rescue_proc_id] = proc_id
end

#emit_prelude(code) ⇒ Object



75
76
77
# File 'lib/tipi/config_dsl.rb', line 75

def emit_prelude(code)
  @stack.last[:prelude] << code
end

#from_source(code) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/tipi/config_dsl.rb', line 34

def from_source(code)
  @stack = [new_frame]
  @app_procs = {}
  @interpreter = Interpreter.new self
  @interpreter.instance_eval code

  loop do
    frame = @stack.pop
    return assemble_app_proc(frame).join("\n") if @stack.empty?

    @stack.last[:body] << assemble_frame(frame)
  end
end

#indent_line(code, indent) ⇒ Object



136
137
138
# File 'lib/tipi/config_dsl.rb', line 136

def indent_line(code, indent)
  indent == 0 ? code : "#{ @@indents[indent] }#{code}"
end

#new_frameObject



48
49
50
51
52
53
# File 'lib/tipi/config_dsl.rb', line 48

def new_frame
  {
    prelude: [],
    body: []
  }
end

#wrap_current_frame(head) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/tipi/config_dsl.rb', line 63

def wrap_current_frame(head)
  frame = @stack.pop
  wrapper = new_frame
  wrapper[:body] << head
  @stack.push wrapper
  @stack.push frame
end