Class: GV_FSM::FSM

Inherits:
Object
  • Object
show all
Includes:
Templates
Defined in:
lib/gv_fsm.rb

Constant Summary

Constants included from Templates

Templates::CC, Templates::HEADER, Templates::HH

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename = nil) ⇒ FSM

Returns a new instance of FSM.



16
17
18
19
20
21
22
23
24
25
# File 'lib/gv_fsm.rb', line 16

def initialize(filename = nil)
  @prefix = ""
  @syslog = true
  @ino = false
  @error = nil
  @matrix = nil
  @nodemap = {}
  @sigint = nil
  parse(filename) if filename
end

Instance Attribute Details

#cnameObject

Returns the value of attribute cname.



13
14
15
# File 'lib/gv_fsm.rb', line 13

def cname
  @cname
end

#descriptionObject

Returns the value of attribute description.



13
14
15
# File 'lib/gv_fsm.rb', line 13

def description
  @description
end

#dotfileObject (readonly)

Returns the value of attribute dotfile.



12
13
14
# File 'lib/gv_fsm.rb', line 12

def dotfile
  @dotfile
end

#errorObject (readonly)

Returns the value of attribute error.



12
13
14
# File 'lib/gv_fsm.rb', line 12

def error
  @error
end

#inoObject

Returns the value of attribute ino.



13
14
15
# File 'lib/gv_fsm.rb', line 13

def ino
  @ino
end

#prefixObject

Returns the value of attribute prefix.



12
13
14
# File 'lib/gv_fsm.rb', line 12

def prefix
  @prefix
end

#project_nameObject

Returns the value of attribute project_name.



13
14
15
# File 'lib/gv_fsm.rb', line 13

def project_name
  @project_name
end

#sigintObject

Returns the value of attribute sigint.



13
14
15
# File 'lib/gv_fsm.rb', line 13

def sigint
  @sigint
end

#statesObject (readonly)

Returns the value of attribute states.



12
13
14
# File 'lib/gv_fsm.rb', line 12

def states
  @states
end

#syslogObject

Returns the value of attribute syslog.



13
14
15
# File 'lib/gv_fsm.rb', line 13

def syslog
  @syslog
end

#transitionsObject (readonly)

Returns the value of attribute transitions.



12
13
14
# File 'lib/gv_fsm.rb', line 12

def transitions
  @transitions
end

Instance Method Details

#destinationsObject



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

def destinations
  dest = Hash[states_list.map {|x| [x, []]}]
  @transitions.each do |t|
    dest[t[:from]] = [] unless dest[t[:from]]
    dest[t[:from]] << t[:to]
  end
  return dest
end

#generate_c(filename = @cname) ⇒ Object



143
144
145
146
147
148
149
150
151
# File 'lib/gv_fsm.rb', line 143

def generate_c(filename = @cname)
  ext = @ino ? "cpp" : "c"
  fname = "#{filename}.#{ext}"
  File.open(fname, "w") do |f|
    f.puts ERB.new(HEADER, 0, "<>").result(binding)
    f.puts ERB.new(CC, 0, "<>").result(binding)
  end
  return fname
end

#generate_h(filename = @cname) ⇒ Object



153
154
155
156
157
158
159
160
# File 'lib/gv_fsm.rb', line 153

def generate_h(filename = @cname)
  fname = "#{filename}.h"
  File.open(fname, "w") do |f|
    f.puts ERB.new(HEADER, 0, "<>").result(binding)
    f.puts ERB.new(HH, 0, "<>").result(binding)
  end
  return fname
end

#parse(filename) ⇒ Object

Raises:

  • (ArgumentError)


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
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
# File 'lib/gv_fsm.rb', line 31

def parse(filename)
  raise ArgumentError, "File must be in .dot format" unless File.extname(filename) == ".dot"
  @cname = File.basename(filename, ".dot") unless (@cname and ! @cname.empty?)
  @dotfile = filename
  @states = []
  @transitions = []
  graph = GraphViz.parse(filename) do |g|
    if g.graph_count > 1 then
      @error = "Only one graph in the dot file is permitted"
      return nil
    end
    unless g.type == "digraph" then
      @error = "Graph is not directed"
      return nil
    end
    n = g.node_count
    if n == 0 then
      @error = "Graph is empty"
      return nil
    end
    @matrix = Matrix.zero(n, n)
    @description = g.name unless @description
    i = 0
    g.each_node do |id|
      n = g.get_node(id)
      if n[:label].source.empty? or
        (n[:label].source == id and !n[:label].source.match(/^do_/)) then
        label = "do_#{id}"
      else
        label = n[:label].source
      end
      @nodemap[id] = i
      i += 1
      @states << {id: id, function: @prefix+label}
    end
    g.each_edge do |e|
      @matrix[@nodemap[e.node_one], @nodemap[e.node_two]] += 1
      from = e.node_one
      to = e.node_two
      unless e[:label] then
        @transitions << {from: from, to: to, function: nil} 
        next
      end
      case e[:label].source
      when ""
        label = nil
      when /[#]/
        label = "#{from}_to_#{to}"
      else
        label = e[:label].source
      end
      @transitions << {from: from, to: to, function: label ? @prefix+label : nil}
    end
  end
  unless graph then 
    @error = "Parsing error"
    return nil
  end
  if (self.sigint && !states.find {|s| s[:id] == self.sigint}) then
    @error = "Missing SIGINT state #{self.sigint}"
    return nil
  end
  return graph
end

#state_functions_listObject



96
97
98
# File 'lib/gv_fsm.rb', line 96

def state_functions_list
  @states.map {|s| s[:function]}
end

#states_listObject



100
101
102
# File 'lib/gv_fsm.rb', line 100

def states_list
  @states.map {|s| s[:id]}
end

#topologyObject



162
163
164
165
166
167
168
169
170
# File 'lib/gv_fsm.rb', line 162

def topology
  res = {matrix: @matrix}
  # rows have the number of froms, columns the number of tos
  res[:froms] = @matrix.row_vectors.map {|v| v.sum }
  res[:tos] = @matrix.column_vectors.map {|v| v.sum }
  res[:sinks] = res[:froms].each_index.select {|i| res[:froms][i] == 0}.map {|i| @nodemap.keys[i]}
  res[:sources] = res[:tos].each_index.select {|i| res[:tos][i] == 0}.map {|i| @nodemap.keys[i]}
  return res
end

#transition_functions_listObject



104
105
106
107
108
109
110
111
112
# File 'lib/gv_fsm.rb', line 104

def transition_functions_list
  lst = []
  @transitions.each do |t|
    if t[:function] and !lst.include? t[:function] then
      lst << (t[:function] or "NULL")
    end
  end
  return lst
end

#transitions_mapObject



114
115
116
117
118
119
120
121
122
123
# File 'lib/gv_fsm.rb', line 114

def transitions_map
  idx = {}
  map = Array.new(@states.count)
  map.map! {|e| e = Array.new(@states.count, "NULL")}
  states_list.each_with_index {|s, i| idx[s] = i }
  @transitions.each do |t|
    map[idx[t[:from]]][idx[t[:to]]] = (t[:function] or "NULL")
  end
  map
end

#transitions_pathsObject



134
135
136
137
138
139
140
141
# File 'lib/gv_fsm.rb', line 134

def transitions_paths
  path = {}
  @transitions.each do |t|
    path[t[:function]] = [] unless path[t[:function]]
    path[t[:function]] << {from: t[:from], to: t[:to]}
  end
  return path
end