Class: Damsi::DFG

Inherits:
Object
  • Object
show all
Defined in:
lib/damsi/dfg.rb

Overview

Dataflow Graph (DFG)

Author

Yegor Bugayenko ([email protected])

Copyright

Copyright © 2023 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

#initialize(prog, log) ⇒ DFG

Returns a new instance of DFG.



28
29
30
31
32
33
34
35
36
37
# File 'lib/damsi/dfg.rb', line 28

def initialize(prog, log)
  @prog = prog
  @log = log
  @cells = {}
  @ops = {}
  @ticks = Damsi::Ticks.new
  @tick = 0
  @op = nil
  @started = []
end

Instance Method Details

#cell(vtx) ⇒ Object



39
40
41
# File 'lib/damsi/dfg.rb', line 39

def cell(vtx)
  @cells[vtx]
end

#msg(tex) ⇒ Object



43
44
45
# File 'lib/damsi/dfg.rb', line 43

def msg(tex)
  @ticks.push(@tick, "\\texttt{\\frenchspacing{}#{@op}: #{tex}}")
end

#recv(vtx, &block) ⇒ Object



56
57
58
# File 'lib/damsi/dfg.rb', line 56

def recv(vtx, &block)
  @ops[vtx] = block
end

#send(vtx, args) ⇒ Object



47
48
49
50
51
52
53
54
# File 'lib/damsi/dfg.rb', line 47

def send(vtx, args)
  @cells[vtx] = {} if @cells[vtx].nil?
  args.each do |k, a|
    @cells[vtx][k] = a
    @ticks.push(@tick, "\\texttt{\\frenchspacing{}#{@op}: \"#{a}\" → #{vtx}.#{k}}")
    @log.debug("#{@tick}| #{a} -> #{vtx}.#{k}")
  end
end

#simulateObject

Returns an instance of Ticks.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/damsi/dfg.rb', line 61

def simulate
  # rubocop:disable Security/Eval
  eval(@prog)
  # rubocop:enable Security/Eval
  loop do
    execs = 0
    before = @cells.clone
    before.each do |v, c|
      next if @ops[v].nil?
      blk = @ops[v]
      reqs = blk.parameters.select { |p| p[0] == :opt }.map { |p| p[1] }
      args = reqs.map { |r| [r, c[r]] }.to_h
      bound = args.map { |p| p[1] }.compact
      if bound.size < args.size
        @log.debug("#{@tick}| :#{v}(#{reqs.join(', ')}) is not ready to start with #{args}")
        next
      end
      @log.debug("#{@tick}| :#{v} starts with #{args} ...")
      @op = v
      blk.call(*bound)
      @log.debug("#{@tick}| :#{v} finished")
      execs += 1
      @cells.delete(v)
    end
    @ops.each do |v, blk|
      reqs = blk.parameters.select { |p| p[0] == :opt }.map { |p| p[1] }
      next unless reqs.empty?
      next if @started.include?(v)
      @started.push(v)
      @log.debug("#{@tick}| :#{v} starts empty ...")
      @op = v
      blk.call
      @log.debug("#{@tick}| :#{v} finished")
      execs += 1
    end
    if execs.zero?
      @log.debug("#{@tick}| no executions at #{before.count} operators, we stop here:\n#{before}")
      break
    end
    @tick += 1
    raise 'Ran out of ticks' if @tick > 100
  end
  @ticks
end