fsm 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/gemspec.rb +23 -0
- data/install.rb +206 -0
- data/instance_exec.rb +26 -0
- data/lib/fsm-0.0.0.rb +78 -0
- data/lib/fsm-0.0.0/dsl.rb +71 -0
- data/lib/fsm-0.0.0/event.rb +68 -0
- data/lib/fsm-0.0.0/fsm.rb +211 -0
- data/lib/fsm-0.0.0/fsm.rb.bak +366 -0
- data/lib/fsm-0.0.0/graph/base_extensions.rb +70 -0
- data/lib/fsm-0.0.0/graph/directed_graph.rb +481 -0
- data/lib/fsm-0.0.0/graph/graphviz_dot.rb +188 -0
- data/lib/fsm-0.0.0/observer.rb +194 -0
- data/lib/fsm-0.0.0/system.rb +65 -0
- data/lib/fsm-0.0.0/util.rb +172 -0
- data/lib/fsm.rb +78 -0
- data/sample/a.rb +81 -0
- metadata +58 -0
data/gemspec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
Gem::Specification::new do |spec|
|
6
|
+
spec.name = lib
|
7
|
+
spec.version = version
|
8
|
+
spec.platform = Gem::Platform::RUBY
|
9
|
+
spec.summary = lib
|
10
|
+
|
11
|
+
spec.files = Dir::glob "**/**"
|
12
|
+
spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
|
13
|
+
|
14
|
+
spec.require_path = "lib"
|
15
|
+
spec.autorequire = lib
|
16
|
+
|
17
|
+
spec.has_rdoc = File::exist? "doc"
|
18
|
+
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
19
|
+
|
20
|
+
spec.author = "Ara T. Howard"
|
21
|
+
spec.email = "ara.t.howard@noaa.gov"
|
22
|
+
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
23
|
+
end
|
data/install.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'find'
|
4
|
+
require 'ftools'
|
5
|
+
require 'tempfile'
|
6
|
+
include Config
|
7
|
+
|
8
|
+
LIBDIR = "lib"
|
9
|
+
LIBDIR_MODE = 0644
|
10
|
+
|
11
|
+
BINDIR = "bin"
|
12
|
+
BINDIR_MODE = 0755
|
13
|
+
|
14
|
+
|
15
|
+
$srcdir = CONFIG["srcdir"]
|
16
|
+
$version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
17
|
+
$libdir = File.join(CONFIG["libdir"], "ruby", $version)
|
18
|
+
$archdir = File.join($libdir, CONFIG["arch"])
|
19
|
+
$site_libdir = $:.find {|x| x =~ /site_ruby$/}
|
20
|
+
$bindir = CONFIG["bindir"] || CONFIG['BINDIR']
|
21
|
+
$ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
|
22
|
+
$ruby_ext = CONFIG['EXEEXT'] || ''
|
23
|
+
$ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
|
24
|
+
|
25
|
+
if !$site_libdir
|
26
|
+
$site_libdir = File.join($libdir, "site_ruby")
|
27
|
+
elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
|
28
|
+
$site_libdir = File.join($site_libdir, $version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
|
32
|
+
#{{{
|
33
|
+
path = []
|
34
|
+
dir = []
|
35
|
+
Find.find(srcdir) do |f|
|
36
|
+
next unless FileTest.file?(f)
|
37
|
+
next if (f = f[srcdir.length+1..-1]) == nil
|
38
|
+
next if (/CVS$/ =~ File.dirname(f))
|
39
|
+
next if f =~ %r/\.lnk/
|
40
|
+
path.push f
|
41
|
+
dir |= [File.dirname(f)]
|
42
|
+
end
|
43
|
+
for f in dir
|
44
|
+
next if f == "."
|
45
|
+
next if f == "CVS"
|
46
|
+
File::makedirs(File.join(destdir, f))
|
47
|
+
end
|
48
|
+
for f in path
|
49
|
+
next if (/\~$/ =~ f)
|
50
|
+
next if (/^\./ =~ File.basename(f))
|
51
|
+
unless bin
|
52
|
+
File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
|
53
|
+
else
|
54
|
+
from = File.join(srcdir, f)
|
55
|
+
to = File.join(destdir, f)
|
56
|
+
shebangify(from) do |sf|
|
57
|
+
$deferr.print from, " -> ", File::catname(from, to), "\n"
|
58
|
+
$deferr.printf "chmod %04o %s\n", mode, to
|
59
|
+
File::install(sf, to, mode, false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
#}}}
|
64
|
+
end
|
65
|
+
def shebangify f
|
66
|
+
#{{{
|
67
|
+
open(f) do |fd|
|
68
|
+
buf = fd.read 42
|
69
|
+
if buf =~ %r/^\s*#\s*!.*ruby/o
|
70
|
+
ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
|
71
|
+
begin
|
72
|
+
fd.rewind
|
73
|
+
ftmp.puts "#!#{ $ruby }"
|
74
|
+
while((buf = fd.read(8192)))
|
75
|
+
ftmp.write buf
|
76
|
+
end
|
77
|
+
ftmp.close
|
78
|
+
yield ftmp.path
|
79
|
+
ensure
|
80
|
+
ftmp.close!
|
81
|
+
end
|
82
|
+
else
|
83
|
+
yield f
|
84
|
+
end
|
85
|
+
end
|
86
|
+
#}}}
|
87
|
+
end
|
88
|
+
def ARGV.switch
|
89
|
+
#{{{
|
90
|
+
return nil if self.empty?
|
91
|
+
arg = self.shift
|
92
|
+
return nil if arg == '--'
|
93
|
+
if arg =~ /^-(.)(.*)/
|
94
|
+
return arg if $1 == '-'
|
95
|
+
raise 'unknown switch "-"' if $2.index('-')
|
96
|
+
self.unshift "-#{$2}" if $2.size > 0
|
97
|
+
"-#{$1}"
|
98
|
+
else
|
99
|
+
self.unshift arg
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
#}}}
|
103
|
+
end
|
104
|
+
def ARGV.req_arg
|
105
|
+
#{{{
|
106
|
+
self.shift || raise('missing argument')
|
107
|
+
#}}}
|
108
|
+
end
|
109
|
+
def linkify d, linked = []
|
110
|
+
#--{{{
|
111
|
+
if test ?d, d
|
112
|
+
versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
|
113
|
+
versioned.each do |v|
|
114
|
+
src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
|
115
|
+
lnk = nil
|
116
|
+
begin
|
117
|
+
if test ?l, dst
|
118
|
+
lnk = "#{ dst }.lnk"
|
119
|
+
puts "#{ dst } -> #{ lnk }"
|
120
|
+
File::rename dst, lnk
|
121
|
+
end
|
122
|
+
unless test ?e, dst
|
123
|
+
puts "#{ src } -> #{ dst }"
|
124
|
+
File::copy src, dst
|
125
|
+
linked << dst
|
126
|
+
end
|
127
|
+
ensure
|
128
|
+
if lnk
|
129
|
+
at_exit do
|
130
|
+
puts "#{ lnk } -> #{ dst }"
|
131
|
+
File::rename lnk, dst
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
linked
|
138
|
+
#--}}}
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
#
|
143
|
+
# main program
|
144
|
+
#
|
145
|
+
|
146
|
+
libdir = $site_libdir
|
147
|
+
bindir = $bindir
|
148
|
+
no_linkify = false
|
149
|
+
linked = nil
|
150
|
+
help = false
|
151
|
+
|
152
|
+
usage = <<-usage
|
153
|
+
#{ File::basename $0 }
|
154
|
+
-d, --destdir <destdir>
|
155
|
+
-l, --libdir <libdir>
|
156
|
+
-b, --bindir <bindir>
|
157
|
+
-r, --ruby <ruby>
|
158
|
+
-n, --no_linkify
|
159
|
+
-s, --sudo
|
160
|
+
-h, --help
|
161
|
+
usage
|
162
|
+
|
163
|
+
begin
|
164
|
+
while switch = ARGV.switch
|
165
|
+
case switch
|
166
|
+
when '-d', '--destdir'
|
167
|
+
libdir = ARGV.req_arg
|
168
|
+
when '-l', '--libdir'
|
169
|
+
libdir = ARGV.req_arg
|
170
|
+
when '-b', '--bindir'
|
171
|
+
bindir = ARGV.req_arg
|
172
|
+
when '-r', '--ruby'
|
173
|
+
$ruby = ARGV.req_arg
|
174
|
+
when '-n', '--no_linkify'
|
175
|
+
no_linkify = true
|
176
|
+
when '-s', '--sudo'
|
177
|
+
sudo = 'sudo'
|
178
|
+
when '-h', '--help'
|
179
|
+
help = true
|
180
|
+
else
|
181
|
+
raise "unknown switch #{switch.dump}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
rescue
|
185
|
+
STDERR.puts $!.to_s
|
186
|
+
STDERR.puts usage
|
187
|
+
exit 1
|
188
|
+
end
|
189
|
+
|
190
|
+
if help
|
191
|
+
STDOUT.puts usage
|
192
|
+
exit
|
193
|
+
end
|
194
|
+
|
195
|
+
unless no_linkify
|
196
|
+
linked = linkify('lib') + linkify('bin')
|
197
|
+
end
|
198
|
+
|
199
|
+
system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
|
200
|
+
|
201
|
+
install_rb(LIBDIR, libdir, LIBDIR_MODE)
|
202
|
+
install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
|
203
|
+
|
204
|
+
if linked
|
205
|
+
linked.each{|path| File::rm_f path}
|
206
|
+
end
|
data/instance_exec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
class Object
|
3
|
+
unless instance_methods.include? 'instance_exec'
|
4
|
+
def instance_exec *a, &b
|
5
|
+
m = "__instance_exec_#{ Thread.current.object_id.abs }__"
|
6
|
+
singleton_class{ define_method m, &b }
|
7
|
+
send m, *a
|
8
|
+
ensure
|
9
|
+
singleton_class{ undef_method m } rescue nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
unless instance_methods.include? 'singleton_class'
|
13
|
+
def singleton_class &b
|
14
|
+
sc =
|
15
|
+
class << self; self; end
|
16
|
+
sc.module_eval &b if b
|
17
|
+
sc
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
a = []
|
23
|
+
a.instance_exec 42 do |elem|
|
24
|
+
push elem
|
25
|
+
end
|
26
|
+
p a
|
data/lib/fsm-0.0.0.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
unless defined? $__fsm__
|
2
|
+
$__fsm__ = __FILE__
|
3
|
+
|
4
|
+
module FSM
|
5
|
+
#--{{{
|
6
|
+
FSM::LIBNAME =
|
7
|
+
'fsm' unless
|
8
|
+
defined? FSM::LIBNAME
|
9
|
+
|
10
|
+
FSM::VERSION =
|
11
|
+
'0.0.0' unless
|
12
|
+
defined? FSM::VERSION
|
13
|
+
|
14
|
+
FSM::LIBVER =
|
15
|
+
"#{ FSM::LIBNAME }-#{ FSM::VERSION }" unless
|
16
|
+
defined? FSM::LIBVER
|
17
|
+
|
18
|
+
FSM::DIRNAME =
|
19
|
+
File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
|
20
|
+
defined? FSM::DIRNAME
|
21
|
+
|
22
|
+
FSM::ROOTDIR =
|
23
|
+
File::dirname(FSM::DIRNAME) unless
|
24
|
+
defined? FSM::ROOTDIR
|
25
|
+
|
26
|
+
FSM::LIBDIR =
|
27
|
+
File::join(FSM::DIRNAME, FSM::LIBVER) + File::SEPARATOR unless
|
28
|
+
defined? FSM::LIBDIR
|
29
|
+
|
30
|
+
FSM::INCDIR =
|
31
|
+
File::dirname(FSM::LIBDIR) + File::SEPARATOR unless
|
32
|
+
defined? FSM::INCDIR
|
33
|
+
|
34
|
+
FSM::DISPLAY_CMD =
|
35
|
+
ENV['FSM_DISPLAY_CMD'] || 'display'
|
36
|
+
|
37
|
+
FSM::DOT_CMD =
|
38
|
+
ENV['FSM_DOT_CMD'] || 'dot'
|
39
|
+
|
40
|
+
require 'tempfile'
|
41
|
+
require 'thread'
|
42
|
+
require 'sync'
|
43
|
+
require 'enumerator'
|
44
|
+
|
45
|
+
begin
|
46
|
+
$:.unshift LIBDIR
|
47
|
+
require 'graph/directed_graph'
|
48
|
+
ensure
|
49
|
+
$:.shift
|
50
|
+
end
|
51
|
+
|
52
|
+
require LIBDIR + 'util'
|
53
|
+
require LIBDIR + 'event'
|
54
|
+
require LIBDIR + 'fsm'
|
55
|
+
require LIBDIR + 'observer'
|
56
|
+
require LIBDIR + 'system'
|
57
|
+
require LIBDIR + 'dsl'
|
58
|
+
|
59
|
+
def self.new(*a, &b) FSM.new(*a, &b) end
|
60
|
+
def self.system(*a, &b) System.new(*a, &b) end
|
61
|
+
|
62
|
+
module ::Kernel
|
63
|
+
def FSM(*a, &b) ::FSM.new(*a, &b) end
|
64
|
+
def FSMSystem(*a, &b) ::FSM::System.new(*a, &b) end
|
65
|
+
end
|
66
|
+
#--}}}
|
67
|
+
end # module FSM
|
68
|
+
|
69
|
+
class Thread
|
70
|
+
def joinable
|
71
|
+
@joinable = false unless defined? @joinable
|
72
|
+
end
|
73
|
+
alias_method 'joinable?', 'joinable'
|
74
|
+
def joinable= bool
|
75
|
+
@joinable = bool ? true : false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
unless defined? $__fsm_dsl__
|
2
|
+
$__fsm_dsl__ = __FILE__
|
3
|
+
|
4
|
+
module FSM
|
5
|
+
FSM::LIBDIR =
|
6
|
+
File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
|
7
|
+
defined? FSM::LIBDIR
|
8
|
+
|
9
|
+
FSM::INCDIR =
|
10
|
+
File::dirname(FSM::LIBDIR) + File::SEPARATOR unless
|
11
|
+
defined? FSM::INCDIR
|
12
|
+
|
13
|
+
require INCDIR + 'fsm'
|
14
|
+
|
15
|
+
class GenericDSL
|
16
|
+
def initialize object
|
17
|
+
@object = object
|
18
|
+
end
|
19
|
+
def method_missing m, *a, &b
|
20
|
+
if @object.respond_to? m
|
21
|
+
@object.send m, *a, &b
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def configure &b
|
27
|
+
instance_eval &b
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class FSM
|
32
|
+
class DSL < GenericDSL
|
33
|
+
def states *a
|
34
|
+
@object.add_state *a
|
35
|
+
end
|
36
|
+
alias_method 'state', 'states'
|
37
|
+
|
38
|
+
def transition *a, &b
|
39
|
+
@object.add_transition *a, &b
|
40
|
+
end
|
41
|
+
alias_method 'transitioning', 'transition'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Observer
|
46
|
+
class DSL < GenericDSL
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class System
|
51
|
+
class DSL < GenericDSL
|
52
|
+
def fsm &b
|
53
|
+
b ? fsm.configure(&b) : @object.fsm
|
54
|
+
end
|
55
|
+
|
56
|
+
def observer &b
|
57
|
+
b ? observer.configure(&b) : @object.observer
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_missing m, *a, &b
|
61
|
+
if fsm.respond_to? m
|
62
|
+
fsm.send m, *a, &b
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end # module FSM
|
71
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
unless defined? $__fsm_event__
|
2
|
+
$__fsm_event__ = __FILE__
|
3
|
+
|
4
|
+
module FSM
|
5
|
+
FSM::LIBDIR =
|
6
|
+
File::dirname(File::expand_path(__FILE__)) + File::SEPARATOR unless
|
7
|
+
defined? FSM::LIBDIR
|
8
|
+
|
9
|
+
FSM::INCDIR =
|
10
|
+
File::dirname(FSM::LIBDIR) + File::SEPARATOR unless
|
11
|
+
defined? FSM::INCDIR
|
12
|
+
|
13
|
+
require INCDIR + 'fsm'
|
14
|
+
|
15
|
+
class Event
|
16
|
+
include Util
|
17
|
+
|
18
|
+
NOTIFICATION = "fsm_event"
|
19
|
+
|
20
|
+
tattrs %w[
|
21
|
+
state
|
22
|
+
data
|
23
|
+
type
|
24
|
+
]
|
25
|
+
|
26
|
+
def initialize state, *data, &b
|
27
|
+
super
|
28
|
+
@state, @data = state, *data
|
29
|
+
@type = self.class
|
30
|
+
end
|
31
|
+
|
32
|
+
def notify s, *a, &b
|
33
|
+
mcall(s, NOTIFICATION, self, *a, &b) if s.respond_to? NOTIFICATION
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
[@type, @state, @data].inspect
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
class Any < Event
|
42
|
+
end
|
43
|
+
|
44
|
+
class Exit < Any
|
45
|
+
end
|
46
|
+
|
47
|
+
class Transition < Any
|
48
|
+
end
|
49
|
+
|
50
|
+
class Entry < Any
|
51
|
+
end
|
52
|
+
|
53
|
+
class Input < Any
|
54
|
+
end
|
55
|
+
|
56
|
+
TYPES = Any, Exit, Transition, Entry, Input
|
57
|
+
|
58
|
+
def self.message
|
59
|
+
name.split(%r/::/).last.downcase
|
60
|
+
end
|
61
|
+
|
62
|
+
TYPES.each do |etype|
|
63
|
+
message = etype.message
|
64
|
+
singleton_class{ define_method(message){ etype }}
|
65
|
+
end
|
66
|
+
end # class Event
|
67
|
+
end # module FSM
|
68
|
+
end
|