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.
- data/CHANGELOG.md +5 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +46 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +15 -0
- data/README.md +10 -0
- data/Rakefile +11 -0
- data/bin/gvm +9 -0
- data/gisele-vm.gemspec +191 -0
- data/gisele-vm.noespec +31 -0
- data/lib/gisele-vm.rb +4 -0
- data/lib/gisele-vm/loader.rb +5 -0
- data/lib/gisele-vm/version.rb +16 -0
- data/lib/gisele/compiling.rb +3 -0
- data/lib/gisele/compiling/gisele2gts.rb +143 -0
- data/lib/gisele/compiling/gts.rb +74 -0
- data/lib/gisele/compiling/gts2bytecode.rb +127 -0
- data/lib/gisele/vm.rb +87 -0
- data/lib/gisele/vm/bytecode.rb +84 -0
- data/lib/gisele/vm/bytecode/builder.rb +77 -0
- data/lib/gisele/vm/bytecode/grammar.citrus +116 -0
- data/lib/gisele/vm/bytecode/grammar.rb +19 -0
- data/lib/gisele/vm/bytecode/grammar.sexp.yml +113 -0
- data/lib/gisele/vm/bytecode/printer.rb +35 -0
- data/lib/gisele/vm/command.rb +140 -0
- data/lib/gisele/vm/component.rb +91 -0
- data/lib/gisele/vm/console.rb +58 -0
- data/lib/gisele/vm/enacter.rb +29 -0
- data/lib/gisele/vm/errors.rb +26 -0
- data/lib/gisele/vm/event.rb +11 -0
- data/lib/gisele/vm/event_manager.rb +65 -0
- data/lib/gisele/vm/kernel.rb +58 -0
- data/lib/gisele/vm/kernel/macros.gvm +214 -0
- data/lib/gisele/vm/kernel/opcodes.rb +212 -0
- data/lib/gisele/vm/kernel/runner.rb +63 -0
- data/lib/gisele/vm/lifecycle.rb +72 -0
- data/lib/gisele/vm/logging.rb +18 -0
- data/lib/gisele/vm/null_object.rb +19 -0
- data/lib/gisele/vm/prog.rb +63 -0
- data/lib/gisele/vm/prog_list.rb +55 -0
- data/lib/gisele/vm/prog_list/memory.rb +74 -0
- data/lib/gisele/vm/prog_list/sqldb.rb +123 -0
- data/lib/gisele/vm/prog_list/storage.rb +31 -0
- data/lib/gisele/vm/proxy.rb +14 -0
- data/lib/gisele/vm/proxy/client.rb +64 -0
- data/lib/gisele/vm/proxy/server.rb +29 -0
- data/lib/gisele/vm/registry.rb +57 -0
- data/lib/gisele/vm/robustness.rb +31 -0
- data/lib/gisele/vm/simulator/resumer.rb +32 -0
- data/spec/command/gvm_compile.cmd +1 -0
- data/spec/command/gvm_compile.stdout +111 -0
- data/spec/command/gvm_gts.cmd +1 -0
- data/spec/command/gvm_gts.stdout +101 -0
- data/spec/command/gvm_help.cmd +1 -0
- data/spec/command/gvm_help.stdout +30 -0
- data/spec/command/gvm_version.cmd +1 -0
- data/spec/command/gvm_version.stdout +2 -0
- data/spec/command/test_command.rb +29 -0
- data/spec/fixtures/complete.gis +13 -0
- data/spec/fixtures/fake_component.rb +24 -0
- data/spec/fixtures/kernel.rb +39 -0
- data/spec/fixtures/ts.adl +11 -0
- data/spec/fixtures/ts.gts +20 -0
- data/spec/fixtures/ts.gvm +19 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/test_examples.rb +29 -0
- data/spec/test_gisele-vm.rb +8 -0
- data/spec/unit/bytecode/builder/test_at.rb +56 -0
- data/spec/unit/bytecode/builder/test_helpers.rb +36 -0
- data/spec/unit/bytecode/builder/test_instruction.rb +35 -0
- data/spec/unit/bytecode/builder/test_to_a.rb +53 -0
- data/spec/unit/bytecode/bytecode.gvm +1 -0
- data/spec/unit/bytecode/grammar/fixtures/comments.gvm +16 -0
- data/spec/unit/bytecode/grammar/fixtures/every.gvm +46 -0
- data/spec/unit/bytecode/grammar/fixtures/singleblock.gvm +2 -0
- data/spec/unit/bytecode/grammar/fixtures/twoblocks.gvm +4 -0
- data/spec/unit/bytecode/grammar/fixtures/with_end.gvm +5 -0
- data/spec/unit/bytecode/grammar/test_array.rb +24 -0
- data/spec/unit/bytecode/grammar/test_block.rb +35 -0
- data/spec/unit/bytecode/grammar/test_boolean.rb +20 -0
- data/spec/unit/bytecode/grammar/test_constant.rb +20 -0
- data/spec/unit/bytecode/grammar/test_eol.rb +20 -0
- data/spec/unit/bytecode/grammar/test_eol_comment.rb +36 -0
- data/spec/unit/bytecode/grammar/test_file.rb +38 -0
- data/spec/unit/bytecode/grammar/test_hash.rb +33 -0
- data/spec/unit/bytecode/grammar/test_instruction.rb +32 -0
- data/spec/unit/bytecode/grammar/test_int.rb +24 -0
- data/spec/unit/bytecode/grammar/test_label.rb +24 -0
- data/spec/unit/bytecode/grammar/test_opcode.rb +23 -0
- data/spec/unit/bytecode/grammar/test_string.rb +25 -0
- data/spec/unit/bytecode/grammar/test_symbol.rb +30 -0
- data/spec/unit/bytecode/test_build.rb +36 -0
- data/spec/unit/bytecode/test_coerce.rb +41 -0
- data/spec/unit/bytecode/test_fetch.rb +20 -0
- data/spec/unit/bytecode/test_grammar.rb +30 -0
- data/spec/unit/bytecode/test_parse.rb +22 -0
- data/spec/unit/bytecode/test_plus.rb +27 -0
- data/spec/unit/bytecode/test_to_a.rb +19 -0
- data/spec/unit/bytecode/test_to_s.rb +32 -0
- data/spec/unit/command/code.gis +3 -0
- data/spec/unit/command/test_vm.rb +51 -0
- data/spec/unit/compiling/gisele2gts/test_on_par_st.rb +51 -0
- data/spec/unit/compiling/gisele2gts/test_on_seq_st.rb +46 -0
- data/spec/unit/compiling/gisele2gts/test_on_task_call_st.rb +37 -0
- data/spec/unit/compiling/gisele2gts/test_on_task_def.rb +49 -0
- data/spec/unit/compiling/gisele2gts/test_on_unit_def.rb +35 -0
- data/spec/unit/compiling/gts2bytecode/test_on_end.rb +31 -0
- data/spec/unit/compiling/gts2bytecode/test_on_event.rb +37 -0
- data/spec/unit/compiling/gts2bytecode/test_on_fork.rb +41 -0
- data/spec/unit/compiling/gts2bytecode/test_on_join.rb +42 -0
- data/spec/unit/compiling/gts2bytecode/test_on_listen.rb +36 -0
- data/spec/unit/compiling/gts2bytecode/test_on_nop.rb +30 -0
- data/spec/unit/component/test_component_name.rb +16 -0
- data/spec/unit/component/test_logging.rb +36 -0
- data/spec/unit/enacter/test_component.rb +11 -0
- data/spec/unit/event/test_to_s.rb +12 -0
- data/spec/unit/event_manager/test_component.rb +9 -0
- data/spec/unit/event_manager/test_subscribe.rb +40 -0
- data/spec/unit/event_manager/test_unsubscribe.rb +39 -0
- data/spec/unit/kernel/macros/test_fork.rb +37 -0
- data/spec/unit/kernel/macros/test_join.rb +43 -0
- data/spec/unit/kernel/macros/test_listen.rb +37 -0
- data/spec/unit/kernel/macros/test_notify.rb +57 -0
- data/spec/unit/kernel/macros/test_react.rb +47 -0
- data/spec/unit/kernel/macros/test_schedule_at.rb +30 -0
- data/spec/unit/kernel/opcodes/test_op_del.rb +42 -0
- data/spec/unit/kernel/opcodes/test_op_event.rb +25 -0
- data/spec/unit/kernel/opcodes/test_op_fetch.rb +27 -0
- data/spec/unit/kernel/opcodes/test_op_flip.rb +17 -0
- data/spec/unit/kernel/opcodes/test_op_fold.rb +29 -0
- data/spec/unit/kernel/opcodes/test_op_fork.rb +63 -0
- data/spec/unit/kernel/opcodes/test_op_forka.rb +51 -0
- data/spec/unit/kernel/opcodes/test_op_get.rb +62 -0
- data/spec/unit/kernel/opcodes/test_op_getr.rb +48 -0
- data/spec/unit/kernel/opcodes/test_op_ifenil.rb +41 -0
- data/spec/unit/kernel/opcodes/test_op_ifezero.rb +32 -0
- data/spec/unit/kernel/opcodes/test_op_invoke.rb +34 -0
- data/spec/unit/kernel/opcodes/test_op_nop.rb +18 -0
- data/spec/unit/kernel/opcodes/test_op_parent.rb +39 -0
- data/spec/unit/kernel/opcodes/test_op_pop.rb +22 -0
- data/spec/unit/kernel/opcodes/test_op_push.rb +17 -0
- data/spec/unit/kernel/opcodes/test_op_save.rb +32 -0
- data/spec/unit/kernel/opcodes/test_op_savea.rb +34 -0
- data/spec/unit/kernel/opcodes/test_op_self.rb +20 -0
- data/spec/unit/kernel/opcodes/test_op_send.rb +20 -0
- data/spec/unit/kernel/opcodes/test_op_set.rb +61 -0
- data/spec/unit/kernel/opcodes/test_op_then.rb +50 -0
- data/spec/unit/kernel/opcodes/test_op_unfold.rb +22 -0
- data/spec/unit/kernel/opcodes/test_op_uuid.rb +16 -0
- data/spec/unit/kernel/runner/test_pop.rb +26 -0
- data/spec/unit/kernel/runner/test_stack.rb +28 -0
- data/spec/unit/kernel/test_progress.rb +47 -0
- data/spec/unit/kernel/test_resume.rb +53 -0
- data/spec/unit/kernel/test_start.rb +36 -0
- data/spec/unit/prog/test_to_hash.rb +29 -0
- data/spec/unit/prog/test_waitlist_eq.rb +20 -0
- data/spec/unit/prog_list/memory/test_component.rb +9 -0
- data/spec/unit/prog_list/memory/test_fetch.rb +40 -0
- data/spec/unit/prog_list/memory/test_pick.rb +39 -0
- data/spec/unit/prog_list/memory/test_save.rb +91 -0
- data/spec/unit/prog_list/memory/test_to_relation.rb +17 -0
- data/spec/unit/prog_list/sqldb/test_component.rb +11 -0
- data/spec/unit/prog_list/sqldb/test_connect.rb +46 -0
- data/spec/unit/prog_list/test_memory.rb +9 -0
- data/spec/unit/prog_list/test_sqldb.rb +13 -0
- data/spec/unit/prog_list/test_storage.rb +51 -0
- data/spec/unit/registry/test_component.rb +9 -0
- data/spec/unit/registry/test_connect.rb +53 -0
- data/spec/unit/registry/test_disconnect.rb +51 -0
- data/spec/unit/registry/test_registration.rb +44 -0
- data/spec/unit/shared/a_component.rb +49 -0
- data/spec/unit/shared/a_storage.rb +114 -0
- data/spec/unit/test_logging.rb +46 -0
- data/spec/unit/test_prog.rb +57 -0
- data/spec/unit/test_prog_list.rb +22 -0
- data/spec/unit/vm/test_event_facace.rb +11 -0
- data/spec/unit/vm/test_initialize.rb +59 -0
- data/spec/unit/vm/test_proglist_facade.rb +21 -0
- data/tasks/debug_mail.rake +75 -0
- data/tasks/debug_mail.txt +13 -0
- data/tasks/gem.rake +73 -0
- data/tasks/spec_test.rake +71 -0
- data/tasks/unit_test.rake +76 -0
- data/tasks/yard.rake +51 -0
- 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
|