Class: Ramekin::LoopAllocator

Inherits:
Processor show all
Defined in:
lib/ramekin/loop_allocator.rb

Instance Attribute Summary

Attributes inherited from Processor

#stream

Instance Method Summary collapse

Methods inherited from Processor

#buffer, call, compose, #each, #flush!, #next!, #peek

Instance Method Details

#call(&b) ⇒ Object



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
# File 'lib/ramekin/loop_allocator.rb', line 3

def call(&b)
  tokens = @stream.to_a

  loop_defs = tokens.select do |tok|
    Token === tok && tok.type == :loop && tok.value && !tok.value.empty?
  end

  index = 0
  indices = {}
  used = Set.new

  numbered, named = loop_defs.partition do |tok|
    /\A\d+\z/.match?(tok.value)
  end

  numbered.each do |tok|
    num = indices[tok.value] = tok.value.to_i
    tok.meta[:number] = num
    used << num
  end

  named.each do |tok|
    if indices.key?(tok.value)
      error! "multiple definitions of (#{tok.value})", el: tok
      next
    end

    index += 1
    index += 1 while used.include?(index)
    indices[tok.value] = index
    tok.meta[:number] = index
  end

  tokens.each do |token|
    if Token === token && token.type == :loop_call
      token.meta[:number] = indices.fetch(token.value) do
        error! "no such loop", el: token
      end
    end

    yield token
  end
end