gisele-vm 0.6.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.
Files changed (185) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +18 -0
  3. data/Gemfile.lock +46 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +15 -0
  6. data/README.md +10 -0
  7. data/Rakefile +11 -0
  8. data/bin/gvm +9 -0
  9. data/gisele-vm.gemspec +191 -0
  10. data/gisele-vm.noespec +31 -0
  11. data/lib/gisele-vm.rb +4 -0
  12. data/lib/gisele-vm/loader.rb +5 -0
  13. data/lib/gisele-vm/version.rb +16 -0
  14. data/lib/gisele/compiling.rb +3 -0
  15. data/lib/gisele/compiling/gisele2gts.rb +143 -0
  16. data/lib/gisele/compiling/gts.rb +74 -0
  17. data/lib/gisele/compiling/gts2bytecode.rb +127 -0
  18. data/lib/gisele/vm.rb +87 -0
  19. data/lib/gisele/vm/bytecode.rb +84 -0
  20. data/lib/gisele/vm/bytecode/builder.rb +77 -0
  21. data/lib/gisele/vm/bytecode/grammar.citrus +116 -0
  22. data/lib/gisele/vm/bytecode/grammar.rb +19 -0
  23. data/lib/gisele/vm/bytecode/grammar.sexp.yml +113 -0
  24. data/lib/gisele/vm/bytecode/printer.rb +35 -0
  25. data/lib/gisele/vm/command.rb +140 -0
  26. data/lib/gisele/vm/component.rb +91 -0
  27. data/lib/gisele/vm/console.rb +58 -0
  28. data/lib/gisele/vm/enacter.rb +29 -0
  29. data/lib/gisele/vm/errors.rb +26 -0
  30. data/lib/gisele/vm/event.rb +11 -0
  31. data/lib/gisele/vm/event_manager.rb +65 -0
  32. data/lib/gisele/vm/kernel.rb +58 -0
  33. data/lib/gisele/vm/kernel/macros.gvm +214 -0
  34. data/lib/gisele/vm/kernel/opcodes.rb +212 -0
  35. data/lib/gisele/vm/kernel/runner.rb +63 -0
  36. data/lib/gisele/vm/lifecycle.rb +72 -0
  37. data/lib/gisele/vm/logging.rb +18 -0
  38. data/lib/gisele/vm/null_object.rb +19 -0
  39. data/lib/gisele/vm/prog.rb +63 -0
  40. data/lib/gisele/vm/prog_list.rb +55 -0
  41. data/lib/gisele/vm/prog_list/memory.rb +74 -0
  42. data/lib/gisele/vm/prog_list/sqldb.rb +123 -0
  43. data/lib/gisele/vm/prog_list/storage.rb +31 -0
  44. data/lib/gisele/vm/proxy.rb +14 -0
  45. data/lib/gisele/vm/proxy/client.rb +64 -0
  46. data/lib/gisele/vm/proxy/server.rb +29 -0
  47. data/lib/gisele/vm/registry.rb +57 -0
  48. data/lib/gisele/vm/robustness.rb +31 -0
  49. data/lib/gisele/vm/simulator/resumer.rb +32 -0
  50. data/spec/command/gvm_compile.cmd +1 -0
  51. data/spec/command/gvm_compile.stdout +111 -0
  52. data/spec/command/gvm_gts.cmd +1 -0
  53. data/spec/command/gvm_gts.stdout +101 -0
  54. data/spec/command/gvm_help.cmd +1 -0
  55. data/spec/command/gvm_help.stdout +30 -0
  56. data/spec/command/gvm_version.cmd +1 -0
  57. data/spec/command/gvm_version.stdout +2 -0
  58. data/spec/command/test_command.rb +29 -0
  59. data/spec/fixtures/complete.gis +13 -0
  60. data/spec/fixtures/fake_component.rb +24 -0
  61. data/spec/fixtures/kernel.rb +39 -0
  62. data/spec/fixtures/ts.adl +11 -0
  63. data/spec/fixtures/ts.gts +20 -0
  64. data/spec/fixtures/ts.gvm +19 -0
  65. data/spec/spec_helper.rb +86 -0
  66. data/spec/test_examples.rb +29 -0
  67. data/spec/test_gisele-vm.rb +8 -0
  68. data/spec/unit/bytecode/builder/test_at.rb +56 -0
  69. data/spec/unit/bytecode/builder/test_helpers.rb +36 -0
  70. data/spec/unit/bytecode/builder/test_instruction.rb +35 -0
  71. data/spec/unit/bytecode/builder/test_to_a.rb +53 -0
  72. data/spec/unit/bytecode/bytecode.gvm +1 -0
  73. data/spec/unit/bytecode/grammar/fixtures/comments.gvm +16 -0
  74. data/spec/unit/bytecode/grammar/fixtures/every.gvm +46 -0
  75. data/spec/unit/bytecode/grammar/fixtures/singleblock.gvm +2 -0
  76. data/spec/unit/bytecode/grammar/fixtures/twoblocks.gvm +4 -0
  77. data/spec/unit/bytecode/grammar/fixtures/with_end.gvm +5 -0
  78. data/spec/unit/bytecode/grammar/test_array.rb +24 -0
  79. data/spec/unit/bytecode/grammar/test_block.rb +35 -0
  80. data/spec/unit/bytecode/grammar/test_boolean.rb +20 -0
  81. data/spec/unit/bytecode/grammar/test_constant.rb +20 -0
  82. data/spec/unit/bytecode/grammar/test_eol.rb +20 -0
  83. data/spec/unit/bytecode/grammar/test_eol_comment.rb +36 -0
  84. data/spec/unit/bytecode/grammar/test_file.rb +38 -0
  85. data/spec/unit/bytecode/grammar/test_hash.rb +33 -0
  86. data/spec/unit/bytecode/grammar/test_instruction.rb +32 -0
  87. data/spec/unit/bytecode/grammar/test_int.rb +24 -0
  88. data/spec/unit/bytecode/grammar/test_label.rb +24 -0
  89. data/spec/unit/bytecode/grammar/test_opcode.rb +23 -0
  90. data/spec/unit/bytecode/grammar/test_string.rb +25 -0
  91. data/spec/unit/bytecode/grammar/test_symbol.rb +30 -0
  92. data/spec/unit/bytecode/test_build.rb +36 -0
  93. data/spec/unit/bytecode/test_coerce.rb +41 -0
  94. data/spec/unit/bytecode/test_fetch.rb +20 -0
  95. data/spec/unit/bytecode/test_grammar.rb +30 -0
  96. data/spec/unit/bytecode/test_parse.rb +22 -0
  97. data/spec/unit/bytecode/test_plus.rb +27 -0
  98. data/spec/unit/bytecode/test_to_a.rb +19 -0
  99. data/spec/unit/bytecode/test_to_s.rb +32 -0
  100. data/spec/unit/command/code.gis +3 -0
  101. data/spec/unit/command/test_vm.rb +51 -0
  102. data/spec/unit/compiling/gisele2gts/test_on_par_st.rb +51 -0
  103. data/spec/unit/compiling/gisele2gts/test_on_seq_st.rb +46 -0
  104. data/spec/unit/compiling/gisele2gts/test_on_task_call_st.rb +37 -0
  105. data/spec/unit/compiling/gisele2gts/test_on_task_def.rb +49 -0
  106. data/spec/unit/compiling/gisele2gts/test_on_unit_def.rb +35 -0
  107. data/spec/unit/compiling/gts2bytecode/test_on_end.rb +31 -0
  108. data/spec/unit/compiling/gts2bytecode/test_on_event.rb +37 -0
  109. data/spec/unit/compiling/gts2bytecode/test_on_fork.rb +41 -0
  110. data/spec/unit/compiling/gts2bytecode/test_on_join.rb +42 -0
  111. data/spec/unit/compiling/gts2bytecode/test_on_listen.rb +36 -0
  112. data/spec/unit/compiling/gts2bytecode/test_on_nop.rb +30 -0
  113. data/spec/unit/component/test_component_name.rb +16 -0
  114. data/spec/unit/component/test_logging.rb +36 -0
  115. data/spec/unit/enacter/test_component.rb +11 -0
  116. data/spec/unit/event/test_to_s.rb +12 -0
  117. data/spec/unit/event_manager/test_component.rb +9 -0
  118. data/spec/unit/event_manager/test_subscribe.rb +40 -0
  119. data/spec/unit/event_manager/test_unsubscribe.rb +39 -0
  120. data/spec/unit/kernel/macros/test_fork.rb +37 -0
  121. data/spec/unit/kernel/macros/test_join.rb +43 -0
  122. data/spec/unit/kernel/macros/test_listen.rb +37 -0
  123. data/spec/unit/kernel/macros/test_notify.rb +57 -0
  124. data/spec/unit/kernel/macros/test_react.rb +47 -0
  125. data/spec/unit/kernel/macros/test_schedule_at.rb +30 -0
  126. data/spec/unit/kernel/opcodes/test_op_del.rb +42 -0
  127. data/spec/unit/kernel/opcodes/test_op_event.rb +25 -0
  128. data/spec/unit/kernel/opcodes/test_op_fetch.rb +27 -0
  129. data/spec/unit/kernel/opcodes/test_op_flip.rb +17 -0
  130. data/spec/unit/kernel/opcodes/test_op_fold.rb +29 -0
  131. data/spec/unit/kernel/opcodes/test_op_fork.rb +63 -0
  132. data/spec/unit/kernel/opcodes/test_op_forka.rb +51 -0
  133. data/spec/unit/kernel/opcodes/test_op_get.rb +62 -0
  134. data/spec/unit/kernel/opcodes/test_op_getr.rb +48 -0
  135. data/spec/unit/kernel/opcodes/test_op_ifenil.rb +41 -0
  136. data/spec/unit/kernel/opcodes/test_op_ifezero.rb +32 -0
  137. data/spec/unit/kernel/opcodes/test_op_invoke.rb +34 -0
  138. data/spec/unit/kernel/opcodes/test_op_nop.rb +18 -0
  139. data/spec/unit/kernel/opcodes/test_op_parent.rb +39 -0
  140. data/spec/unit/kernel/opcodes/test_op_pop.rb +22 -0
  141. data/spec/unit/kernel/opcodes/test_op_push.rb +17 -0
  142. data/spec/unit/kernel/opcodes/test_op_save.rb +32 -0
  143. data/spec/unit/kernel/opcodes/test_op_savea.rb +34 -0
  144. data/spec/unit/kernel/opcodes/test_op_self.rb +20 -0
  145. data/spec/unit/kernel/opcodes/test_op_send.rb +20 -0
  146. data/spec/unit/kernel/opcodes/test_op_set.rb +61 -0
  147. data/spec/unit/kernel/opcodes/test_op_then.rb +50 -0
  148. data/spec/unit/kernel/opcodes/test_op_unfold.rb +22 -0
  149. data/spec/unit/kernel/opcodes/test_op_uuid.rb +16 -0
  150. data/spec/unit/kernel/runner/test_pop.rb +26 -0
  151. data/spec/unit/kernel/runner/test_stack.rb +28 -0
  152. data/spec/unit/kernel/test_progress.rb +47 -0
  153. data/spec/unit/kernel/test_resume.rb +53 -0
  154. data/spec/unit/kernel/test_start.rb +36 -0
  155. data/spec/unit/prog/test_to_hash.rb +29 -0
  156. data/spec/unit/prog/test_waitlist_eq.rb +20 -0
  157. data/spec/unit/prog_list/memory/test_component.rb +9 -0
  158. data/spec/unit/prog_list/memory/test_fetch.rb +40 -0
  159. data/spec/unit/prog_list/memory/test_pick.rb +39 -0
  160. data/spec/unit/prog_list/memory/test_save.rb +91 -0
  161. data/spec/unit/prog_list/memory/test_to_relation.rb +17 -0
  162. data/spec/unit/prog_list/sqldb/test_component.rb +11 -0
  163. data/spec/unit/prog_list/sqldb/test_connect.rb +46 -0
  164. data/spec/unit/prog_list/test_memory.rb +9 -0
  165. data/spec/unit/prog_list/test_sqldb.rb +13 -0
  166. data/spec/unit/prog_list/test_storage.rb +51 -0
  167. data/spec/unit/registry/test_component.rb +9 -0
  168. data/spec/unit/registry/test_connect.rb +53 -0
  169. data/spec/unit/registry/test_disconnect.rb +51 -0
  170. data/spec/unit/registry/test_registration.rb +44 -0
  171. data/spec/unit/shared/a_component.rb +49 -0
  172. data/spec/unit/shared/a_storage.rb +114 -0
  173. data/spec/unit/test_logging.rb +46 -0
  174. data/spec/unit/test_prog.rb +57 -0
  175. data/spec/unit/test_prog_list.rb +22 -0
  176. data/spec/unit/vm/test_event_facace.rb +11 -0
  177. data/spec/unit/vm/test_initialize.rb +59 -0
  178. data/spec/unit/vm/test_proglist_facade.rb +21 -0
  179. data/tasks/debug_mail.rake +75 -0
  180. data/tasks/debug_mail.txt +13 -0
  181. data/tasks/gem.rake +73 -0
  182. data/tasks/spec_test.rake +71 -0
  183. data/tasks/unit_test.rake +76 -0
  184. data/tasks/yard.rake +51 -0
  185. metadata +493 -0
@@ -0,0 +1,212 @@
1
+ module Gisele
2
+ class VM
3
+ class Kernel
4
+ module Opcodes
5
+
6
+ private
7
+
8
+ ### GENERIC OPCODES ################################################################
9
+
10
+ # Pops a method name on the stack unless `method` is specified. Pops an array of
11
+ # argument `args`. Pops an object `receiver`. Invoke `method` on `receiver`, passing
12
+ # arguments `args`. Push the result back on the stack.
13
+ def op_send(method = nil, push_result = true)
14
+ method ||= pop
15
+ args = pop
16
+ receiver = pop
17
+ result = receiver.send(method, *args)
18
+ push result if push_result
19
+ end
20
+
21
+ # Same as `op_send` but does not keep the result on the stack.
22
+ def op_invoke(method = nil)
23
+ op_send(method, false)
24
+ end
25
+
26
+ # Push the value of the attribute `attrname` of the top object. If `attrname` is not
27
+ # specified, pops it from the stack first.
28
+ def op_get(attrname = nil, remove=false)
29
+ attrname ||= pop
30
+ receiver = remove ? pop : peek
31
+ if receiver.respond_to?(:[])
32
+ push receiver[attrname]
33
+ elsif receiver.respond_to?(attrname)
34
+ push receiver.send(attrname)
35
+ else
36
+ raise Error, "Unable to get #{attrname} on #{receiver.inspect}"
37
+ end
38
+ end
39
+
40
+ # Same as +get+ but removes the original receiver from the stack.
41
+ def op_getr(attrname = nil)
42
+ op_get(attrname, true)
43
+ end
44
+
45
+ # If `attrname` is unspecified, pops it from the stack first. Pops a value `val`
46
+ # from the stack. Set attribute `attrname` to `val` on the top object.
47
+ def op_set(attrname = nil)
48
+ attrname ||= pop
49
+ attrvalue = pop
50
+ receiver = peek
51
+ if receiver.respond_to?(:[]=)
52
+ receiver[attrname] = attrvalue
53
+ elsif receiver.respond_to?(:"#{attrname}=")
54
+ receiver.send(:"#{attrname}=", attrvalue)
55
+ else
56
+ raise Error, "Unable to set #{attrname} on #{receiver.inspect}"
57
+ end
58
+ end
59
+
60
+ # If `attrname` is unspecified, pops it from the stack first. Expects an object
61
+ # responding to :delete on top of the stack. Pops it, call `delete(attrname)` on
62
+ # a duplicate and push the later back on the stack.
63
+ def op_del(attrname = nil)
64
+ attrname ||= pop
65
+ push pop.dup
66
+ peek.delete(attrname)
67
+ end
68
+
69
+ ### CONTROL ########################################################################
70
+
71
+ # Does nothing at all
72
+ def op_nop
73
+ end
74
+
75
+ # Pushes opcodes at label `at` on the code queue. If `at` is unspecified, it it
76
+ # poped from the stack first
77
+ def op_then(at = nil)
78
+ enlist_bytecode_at(at || pop)
79
+ end
80
+
81
+ # If the peek object is equal to `val`, flip top operations and skip the first one.
82
+ # Otherwise skip the top operation.
83
+ def op_ifeeq(val = nil)
84
+ if peek == val
85
+ t = opcodes.shift
86
+ opcodes.shift
87
+ opcodes.unshift t
88
+ else
89
+ opcodes.shift
90
+ end
91
+ end
92
+
93
+ # If the peek object is nil, flip top operations and skip the first one. Otherwise
94
+ # skip the top operation.
95
+ def op_ifenil
96
+ op_ifeeq(nil)
97
+ end
98
+
99
+ # If the peek object is zero, flip top operations and skip the first one. Otherwise
100
+ # skip the top operation.
101
+ def op_ifezero
102
+ op_ifeeq(0)
103
+ end
104
+
105
+ ### LIFECYCLE ######################################################################
106
+
107
+ # Puts the puid of the executing Prog on the stack
108
+ def op_puid
109
+ push puid
110
+ end
111
+
112
+ # Push the current Prog on the stack.
113
+ def op_self
114
+ push prog
115
+ end
116
+
117
+ # Pushes the parent Prog of the executing program.
118
+ def op_parent
119
+ push(prog.parent==prog.puid ? nil : vm.fetch(prog.parent))
120
+ end
121
+
122
+ # Fetches the Prog whose id is `puid` and pushes it on the stack. if `puid` is not
123
+ # specified, pops it from the stack first.
124
+ def op_fetch(puid = nil)
125
+ push vm.fetch(puid || pop)
126
+ end
127
+
128
+ def fork(at)
129
+ Prog.new({
130
+ :parent => puid,
131
+ :pc => at,
132
+ :waitfor => :enacter,
133
+ :root => prog && prog.root
134
+ })
135
+ end
136
+ private :fork
137
+
138
+ # Fork the current Prog. Set its program counter to `at` (taken from the stack if
139
+ # not specified), and mark it as schedulable by default. The resulting Prog is
140
+ # pushed on the stack. It is not saved.
141
+ def op_fork(at = nil)
142
+ push fork(at || pop)
143
+ end
144
+
145
+ # Expects an array of labels on the stack. Same as +fork+ but in array version.
146
+ # A resulting array of unsaved Prog is put back on the stack.
147
+ def op_forka(at = nil)
148
+ at ||= pop
149
+ push at.map{|l| fork(l)}
150
+ end
151
+
152
+ # Pops `n` programs from the stack and save them. Pushes their puid back on
153
+ # the stack after saving, in the original order. `n` is considered 1 if unspecified.
154
+ def op_save(n = nil)
155
+ progs = pop(n || 1)
156
+ puids = vm.save(progs)
157
+ puids.reverse.each{|puid| push(puid)}
158
+ end
159
+
160
+ # Expects an array of Progs on the stack. Similar to +save+ but in array version.
161
+ # Push the resulting puids back on the stack in an array.
162
+ def op_savea
163
+ push vm.save(pop)
164
+ end
165
+
166
+ ### DATA STACK MANAGEMENT ##########################################################
167
+
168
+ # Pushes `arg` on the data stack.
169
+ def op_push(arg)
170
+ push arg
171
+ end
172
+
173
+ # Pops the top element from the stack.
174
+ def op_pop(n = nil)
175
+ pop(n)
176
+ end
177
+
178
+ # Flips the two elements on top of the stack
179
+ def op_flip
180
+ pop(2).each{|e| push(e)}
181
+ end
182
+
183
+ # Pops `n` elements from the stack, keep them in a new array and push the later
184
+ # back on the stack. If `n` is not provided, it is taken from the stack first.
185
+ def op_fold(nb = nil)
186
+ n, arr = (nb || pop), []
187
+ n.times{ arr << pop }
188
+ push arr.reverse
189
+ end
190
+
191
+ # Pops an array. Unfolds it on the stack.
192
+ def op_unfold
193
+ pop.each do |elm|
194
+ push elm
195
+ end
196
+ end
197
+
198
+ ### EVENT HANDLING #################################################################
199
+
200
+ # Pops event arguments from the stack (an array). Send an event of the specified
201
+ # kind on the event interface. If `type` is not provided, it is first poped from
202
+ # the stack
203
+ def op_event(type = nil)
204
+ type ||= pop
205
+ args = pop
206
+ vm.event(Event.new(prog, type, args))
207
+ end
208
+
209
+ end # module Opcodes
210
+ end # class Kernel
211
+ end # class VM
212
+ end # module Gisele
@@ -0,0 +1,63 @@
1
+ module Gisele
2
+ class VM
3
+ class Kernel
4
+ class Runner
5
+ include Opcodes
6
+
7
+ attr_reader :vm
8
+ attr_reader :opcodes
9
+ attr_reader :prog
10
+
11
+ def initialize(vm = VM.new, prog = nil)
12
+ @vm = vm
13
+ @prog = prog
14
+ @stack = []
15
+ @opcodes = []
16
+ end
17
+
18
+ def run(at = nil, stack = [])
19
+ @stack = stack
20
+ enlist_bytecode_at(at) if at
21
+ until @opcodes.empty?
22
+ op = @opcodes.shift
23
+ send :"op_#{op.first}", *op[1..-1]
24
+ end
25
+ @stack
26
+ end
27
+
28
+ private
29
+
30
+ ### self
31
+
32
+ def puid
33
+ prog && prog.puid
34
+ end
35
+
36
+ ### stack
37
+
38
+ def push(x)
39
+ @stack << x
40
+ end
41
+
42
+ def pop(n = nil)
43
+ if n.nil?
44
+ @stack.pop
45
+ else
46
+ n.times.map{ @stack.pop }
47
+ end
48
+ end
49
+
50
+ def peek
51
+ @stack.last
52
+ end
53
+
54
+ ### code
55
+
56
+ def enlist_bytecode_at(label)
57
+ @opcodes += vm.bytecode[label]
58
+ end
59
+
60
+ end # class Runner
61
+ end # class Kernel
62
+ end # class VM
63
+ end # module Gisele
@@ -0,0 +1,72 @@
1
+ module Gisele
2
+ class VM
3
+ module Lifecycle
4
+
5
+ attr_reader :status
6
+ attr_reader :last_error
7
+
8
+ def stopped?
9
+ @status == :stopped
10
+ end
11
+
12
+ def running?
13
+ @status == :running
14
+ end
15
+
16
+ def warmup?
17
+ @status == :warmup
18
+ end
19
+
20
+ def shutdown?
21
+ @status == :shutdown
22
+ end
23
+
24
+ def run
25
+ raise InvalidStateError, "VM already running" unless stopped?
26
+ if EM.reactor_running?
27
+ starter
28
+ EM.reactor_thread.join
29
+ else
30
+ EM.error_handler do |ex|
31
+ fatal("EventMachine crashed: #{ex.message}\n" + ex.backtrace.join("\n"))
32
+ if warmup?
33
+ @status = :stopped
34
+ EM.stop_event_loop
35
+ end
36
+ end
37
+ EM::run &method(:starter)
38
+ end
39
+ end
40
+
41
+ def stop
42
+ raise InvalidStateError, "VM not running" unless running?
43
+ @status = :shutdown
44
+ info('VM stop request received, disconnecting.')
45
+ registry.disconnect
46
+ EM.stop_event_loop
47
+ @status = :stopped
48
+ info('VM stopped successfully.')
49
+ end
50
+
51
+ private
52
+
53
+ def init_lifecycle
54
+ @status = :stopped
55
+ end
56
+
57
+ def starter
58
+ @last_error = nil
59
+ @status = :warmup
60
+ info('VM start request received, connecting.')
61
+ registry.connect
62
+ info('Gisele VM has taken stage!')
63
+ @status = :running
64
+ rescue Exception => ex
65
+ fatal("VM start failed.")
66
+ @last_error = ex
67
+ raise
68
+ end
69
+
70
+ end # module Lifecycle
71
+ end # class VM
72
+ end # module Gisele
@@ -0,0 +1,18 @@
1
+ module Gisele
2
+ class VM
3
+ module Logging
4
+ extend Forwardable
5
+
6
+ def logger=(logger)
7
+ @logger = logger
8
+ end
9
+
10
+ def logger
11
+ @logger ||= NullObject.new
12
+ end
13
+
14
+ def_delegators :logger, :debug, :info, :warn, :error, :fatal
15
+ def_delegators :logger, :debug?, :info?, :warn?, :error?, :fatal?
16
+ end # module Logging
17
+ end # class VM
18
+ end # module Gisele
@@ -0,0 +1,19 @@
1
+ module Gisele
2
+ class VM
3
+ class NullObject < BasicObject
4
+
5
+ def method_missing(*args)
6
+ self
7
+ end
8
+
9
+ [ :debug?, :info?, :warn?, :error?, :fatal? ].each do |meth|
10
+ define_method(meth){ false }
11
+ end
12
+
13
+ def to_s
14
+ ''
15
+ end
16
+
17
+ end # class NullObject
18
+ end # class VM
19
+ end # module Gisele
@@ -0,0 +1,63 @@
1
+ module Gisele
2
+ class VM
3
+ class Prog
4
+ attr_accessor :puid
5
+ attr_accessor :parent
6
+ attr_accessor :root
7
+ attr_accessor :pc
8
+ attr_accessor :waitfor
9
+ attr_reader :waitlist
10
+ attr_accessor :input
11
+
12
+ def initialize(attrs = {})
13
+ @puid = attrs[:puid] || nil
14
+ @parent = attrs[:parent] || @puid
15
+ @root = attrs[:root] || @puid
16
+ @pc = attrs[:pc] || :main
17
+ @waitfor = attrs[:waitfor] || :none
18
+ @waitlist = attrs[:waitlist] || {}
19
+ @input = attrs[:input] || []
20
+ end
21
+
22
+ def waitlist=(wlist)
23
+ wlist = Hash[wlist.map{|x| [x,true]}] unless Hash===wlist
24
+ @waitlist = wlist
25
+ end
26
+
27
+ def to_hash(keys = nil)
28
+ if keys
29
+ h = {}
30
+ keys.each do |k|
31
+ h[k] = instance_variable_get(:"@#{k}")
32
+ end
33
+ h
34
+ else
35
+ { :puid => puid,
36
+ :parent => parent,
37
+ :root => root,
38
+ :pc => pc,
39
+ :waitfor => waitfor,
40
+ :waitlist => waitlist,
41
+ :input => input }
42
+ end
43
+ end
44
+
45
+ def dup
46
+ super.tap do |c|
47
+ c.waitlist = waitlist.dup
48
+ c.input = input.dup
49
+ end
50
+ end
51
+
52
+ def ==(other)
53
+ other.is_a?(Prog) and (other.to_hash == to_hash)
54
+ end
55
+ alias :eql? :==
56
+
57
+ def to_s
58
+ "Prog(#{puid.inspect})"
59
+ end
60
+
61
+ end # class Prog
62
+ end # class VM
63
+ end # module Gisele