flok 0.0.38 → 0.0.39

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/drivers/chrome/src/dispatch.js +41 -6
  3. data/app/drivers/chrome/src/persist.js +1 -10
  4. data/app/kern/dispatch.js +17 -23
  5. data/app/kern/gen_id.js +8 -0
  6. data/app/kern/macro.rb +20 -18
  7. data/app/kern/pagers/pg_spec0.js +20 -0
  8. data/app/kern/services/vm.rb +176 -30
  9. data/docs/client_api.md +3 -1
  10. data/docs/compilation.md +1 -1
  11. data/docs/dispatch.md +91 -0
  12. data/docs/kernel_api.md +3 -2
  13. data/docs/messaging.md +6 -1
  14. data/docs/mod/persist.md +4 -3
  15. data/docs/project_layout.md +2 -2
  16. data/docs/services/vm.md +116 -41
  17. data/docs/services/vm/pagers.md +38 -46
  18. data/lib/flok.rb +1 -0
  19. data/lib/flok/build.rb +3 -4
  20. data/lib/flok/macro.rb +27 -0
  21. data/lib/flok/services_compiler.rb +12 -8
  22. data/lib/flok/user_compiler.rb +131 -4
  23. data/lib/flok/version.rb +1 -1
  24. data/spec/env/kern.rb +71 -0
  25. data/spec/etc/macro_spec.rb +3 -8
  26. data/spec/etc/service_compiler/service3.rb +27 -0
  27. data/spec/etc/services_compiler_spec.rb +35 -27
  28. data/spec/iface/driver/dispatch_spec.rb +20 -0
  29. data/spec/iface/driver/persist_spec.rb +9 -24
  30. data/spec/iface/kern/ping_spec.rb +3 -24
  31. data/spec/kern/assets/vm/config4.rb +12 -0
  32. data/spec/kern/assets/vm/controller10.rb +26 -0
  33. data/spec/kern/assets/vm/controller11.rb +33 -0
  34. data/spec/kern/assets/vm/controller12.rb +45 -0
  35. data/spec/kern/assets/vm/controller13.rb +40 -0
  36. data/spec/kern/assets/vm/controller14.rb +14 -0
  37. data/spec/kern/assets/vm/controller15.rb +15 -0
  38. data/spec/kern/assets/vm/controller16.rb +29 -0
  39. data/spec/kern/assets/vm/controller17.rb +30 -0
  40. data/spec/kern/assets/vm/controller18.rb +28 -0
  41. data/spec/kern/assets/vm/controller19.rb +14 -0
  42. data/spec/kern/assets/vm/controller19b.rb +15 -0
  43. data/spec/kern/assets/vm/controller20.rb +19 -0
  44. data/spec/kern/assets/vm/controller21.rb +40 -0
  45. data/spec/kern/assets/vm/controller7.rb +18 -0
  46. data/spec/kern/assets/vm/controller8.rb +38 -0
  47. data/spec/kern/assets/vm/controller8b.rb +18 -0
  48. data/spec/kern/assets/vm/controller9.rb +20 -0
  49. data/spec/kern/assets/vm/controller_exc_2watch.rb +15 -0
  50. data/spec/kern/assets/vm/controller_exc_ewatch.rb +14 -0
  51. data/spec/kern/assets/vm/macros/copy_page_c.rb +23 -0
  52. data/spec/kern/assets/vm/macros/entry_del_c.rb +18 -0
  53. data/spec/kern/assets/vm/macros/entry_insert_c.rb +21 -0
  54. data/spec/kern/assets/vm/macros/entry_mutable_c.rb +33 -0
  55. data/spec/kern/assets/vm/macros/new_page_c.rb +7 -0
  56. data/spec/kern/assets/vm/macros/new_page_c2.rb +7 -0
  57. data/spec/kern/assets/vm/macros/set_page_head_c.rb +18 -0
  58. data/spec/kern/assets/vm/macros/set_page_next_c.rb +18 -0
  59. data/spec/kern/controller_macro_spec.rb +186 -0
  60. data/spec/kern/dispatch_spec.rb +125 -0
  61. data/spec/kern/functions_spec.rb +15 -0
  62. data/spec/kern/vm_service_spec.rb +874 -173
  63. metadata +70 -5
  64. data/docs/scheduling.md +0 -46
  65. data/spec/kern/rest_service_spec.rb +0 -45
data/lib/flok.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "flok/macro"
1
2
  require "flok/version"
2
3
  require "flok/utilities"
3
4
  require "flok/build"
data/lib/flok/build.rb CHANGED
@@ -66,9 +66,8 @@ module Flok
66
66
  Flok.src_glob("js", './app/kern/pagers/', "#{build_path}/glob/3kern.pre_macro.js")
67
67
 
68
68
  #5. All js files in `./products/$PLATFORM/glob/{2,3}kern.pre_macro.js` are run through `./app/kern/macro.rb's macro_process` and then sent to ./products/$PLATFORM/glob/{2,3}kern.js
69
- require './app/kern/macro.rb'
70
- File.write("#{build_path}/glob/2kern.pre_macro.js", macro_process(File.read("#{build_path}/glob/2kern.pre_macro.js")))
71
- File.write("#{build_path}/glob/3kern.pre_macro.js", macro_process(File.read("#{build_path}/glob/3kern.pre_macro.js")))
69
+ File.write("#{build_path}/glob/2kern.pre_macro.js", Flok.macro_process(File.read("#{build_path}/glob/2kern.pre_macro.js")))
70
+ File.write("#{build_path}/glob/3kern.pre_macro.js", Flok.macro_process(File.read("#{build_path}/glob/3kern.pre_macro.js")))
72
71
 
73
72
  #6. All js files are globbed from `./products/$platform/glob` and combined into `./products/$platform/glob/application.js.erb`
74
73
  Flok.src_glob("js", "#{build_path}/glob", "#{build_path}/glob/application.js.erb")
@@ -95,7 +94,7 @@ module Flok
95
94
  mods.each do |mod|
96
95
  s = File.read("./app/kern/mod/#{mod}.js")
97
96
  open("#{build_path}/glob/application.js.erb", "a") do |f|
98
- f.puts macro_process(s)
97
+ f.puts Flok.macro_process(s)
99
98
  end
100
99
  end
101
100
 
data/lib/flok/macro.rb ADDED
@@ -0,0 +1,27 @@
1
+ module Flok
2
+ #Process one js code file at a time
3
+ def self.macro_process text
4
+ out = StringIO.new
5
+
6
+ text.split("\n").each do |l|
7
+ #Send macro
8
+ if l =~ /SEND/
9
+ l.strip!
10
+ l.gsub!(/SEND\(/, "")
11
+ l.gsub! /\)$/, ""
12
+ l.gsub! /\);$/, ""
13
+ o = l.split(",").map{|e| e.strip}
14
+
15
+ queue_name = o.shift.gsub(/"/, "")
16
+
17
+ res = %{#{queue_name}_q.push([#{o.count-1}, #{o.join(", ")}])}
18
+ out.puts res
19
+ else
20
+ out.puts l
21
+ end
22
+ end
23
+
24
+ return out.string
25
+ end
26
+ end
27
+
@@ -17,7 +17,7 @@ module Flok
17
17
  context = ServicesCompilerContext.new(config_context)
18
18
  context.instance_eval(rb_src, __FILE__, __LINE__)
19
19
  context.ready
20
-
20
+
21
21
  @src = ""
22
22
  services_erb = File.read File.join(File.dirname(__FILE__), "./service_compiler_templates/services.js.erb")
23
23
  services_renderer = ERB.new(services_erb)
@@ -95,6 +95,9 @@ module Flok
95
95
 
96
96
  #These are for every 5.seconds
97
97
  @every_handlers = []
98
+
99
+ @debug = true if ENV["FLOK_ENV"] == "DEBUG"
100
+ @release = true if ENV["FLOK_ENV"] == "RELEASE"
98
101
  end
99
102
 
100
103
  def get_on_init
@@ -108,32 +111,32 @@ module Flok
108
111
  def global(str)
109
112
  render = ERB.new(str)
110
113
  str = render.result(binding)
111
- @_global = str
114
+ @_global = macro(str)
112
115
  end
113
116
 
114
117
  def on_wakeup(str)
115
118
  render = ERB.new(str)
116
119
  str = render.result(binding)
117
- @_on_wakeup = str
120
+ @_on_wakeup = macro(str)
118
121
  end
119
122
 
120
123
  def on_sleep(str)
121
124
  render = ERB.new(str)
122
125
  str = render.result(binding)
123
126
 
124
- @_on_sleep = str
127
+ @_on_sleep = macro(str)
125
128
  end
126
129
 
127
130
  def on_connect(str)
128
131
  render = ERB.new(str)
129
132
  str = render.result(binding)
130
- @_on_connect = str
133
+ @_on_connect = macro(str)
131
134
  end
132
135
 
133
136
  def on_disconnect(str)
134
137
  render = ERB.new(str)
135
138
  str = render.result(binding)
136
- @_on_disconnect = str
139
+ @_on_disconnect = macro(str)
137
140
  end
138
141
 
139
142
  def on(name, str)
@@ -142,7 +145,7 @@ module Flok
142
145
 
143
146
  @event_handlers << {
144
147
  :name => name,
145
- :str => str
148
+ :str => macro(str)
146
149
  }
147
150
  end
148
151
 
@@ -150,7 +153,7 @@ module Flok
150
153
  @every_handlers << {
151
154
  :name => "#{seconds}_sec_#{SecureRandom.hex[0..6]}",
152
155
  :ticks => seconds*4,
153
- :str => str
156
+ :str => macro(str)
154
157
  }
155
158
  end
156
159
 
@@ -163,6 +166,7 @@ module Flok
163
166
  end
164
167
 
165
168
  def macro text
169
+ return Flok.macro_process(text)
166
170
  #out = StringIO.new
167
171
 
168
172
  #text.split("\n").each do |l|
@@ -14,7 +14,7 @@ module Flok
14
14
  ctable_erb = File.read File.join(File.dirname(__FILE__), "./user_compiler_templates/ctable.js.erb")
15
15
  ctable_renderer = ERB.new(ctable_erb)
16
16
  @src << ctable_renderer.result(context.get_binding)
17
-
17
+
18
18
  return @src
19
19
  end
20
20
  end
@@ -169,7 +169,6 @@ module Flok
169
169
  int_event(vcs[i], #{event_name}, #{info});
170
170
  }
171
171
  }
172
-
173
172
  #GOTO(action_name)
174
173
  elsif l =~ /Goto/
175
174
  l.strip!
@@ -240,12 +239,140 @@ module Flok
240
239
  name = o.shift.gsub(/"/, "")
241
240
  ename = o.shift.gsub(/"/, "")
242
241
  info = o.shift.gsub(/"/, "")
243
-
244
242
  raise "You tried to Request the service #{name.inspect}, but you haven't added that to your 'services' for this controller (#{@controller.name.inspect})" unless @controller._services.include? name
245
-
246
243
  out << %{
247
244
  #{name}_on_#{ename}(__base__, #{info});
248
245
  }
246
+ #VM Page macros
247
+ elsif l =~ /NewPage/
248
+ le = (l.split /NewPage/)
249
+ lvar = le[0].strip #Probably var x =
250
+ exp = le[1].strip
251
+
252
+ #For CopyPage(original_page), page_var is original_page
253
+ #This only supports variable names at this time
254
+ exp.match /\((.*)\);?/
255
+
256
+ #Get the id value the user wants, but we have to be careful
257
+ #because if nothing is passed, then we need to set it to null
258
+ id_var = $1.strip
259
+ if id_var == ""
260
+ id_var = "null"
261
+ end
262
+
263
+ out << %{
264
+ #{lvar} {
265
+ _head: null,
266
+ _next: null,
267
+ entries: [],
268
+ _id: #{id_var},
269
+ }
270
+ }
271
+ elsif l =~ /CopyPage/
272
+ le = (l.split /CopyPage/)
273
+ lvar = le[0].strip #Probably var x =
274
+ exp = le[1].strip
275
+
276
+ #For CopyPage(original_page), page_var is original_page
277
+ #This only supports variable names at this time
278
+ exp.match /\((.*)\);?/
279
+ page_var = $1
280
+
281
+ out << %{
282
+ var __page__ = {
283
+ _head: #{page_var}._head,
284
+ _next: #{page_var}._next,
285
+ _id: #{page_var}._id,
286
+ entries: [],
287
+ }
288
+
289
+ //This is a shallow clone, but we own this array
290
+ //When a mutable entry needs to be created, an entry will be cloned
291
+ //and swappend out
292
+ for (var i = 0; i < #{page_var}.entries.length; ++i) {
293
+ __page__.entries.push(#{page_var}.entries[i]);
294
+ }
295
+
296
+ #{lvar} __page__;
297
+ }
298
+ elsif l =~ /EntryDel/
299
+ le = (l.split /EntryDel/)
300
+ lvar = le[0].strip #Probably var x =
301
+ exp = le[1].strip
302
+
303
+ #For CopyPage(original_page), page_var is original_page
304
+ #This only supports variable names at this time
305
+ exp.match /\((.*?),(.*)\);?/
306
+ page_var = $1
307
+ index_var = $2
308
+
309
+ out << %{
310
+ #{page_var}.entries.splice(#{index_var}, 1);
311
+ }
312
+
313
+ elsif l =~ /EntryInsert/
314
+ le = (l.split /EntryInsert/)
315
+ lvar = le[0].strip #Probably var x =
316
+ exp = le[1].strip
317
+
318
+ #For CopyPage(original_page), page_var is original_page
319
+ #This only supports variable names at this time
320
+ exp.match /\((.*?),(.*),(.*)\);?/
321
+ page_var = $1
322
+ index_var = $2
323
+ entry_var = $3
324
+
325
+ out << %{
326
+ #{entry_var}._id = gen_id();
327
+ #{entry_var}._sig = gen_id();
328
+ #{page_var}.entries.splice(#{index_var}, 0, #{entry_var});
329
+ }
330
+
331
+ elsif l =~ /SetPageNext/
332
+ le = (l.split /SetPageNext/)
333
+ lvar = le[0].strip #Probably var x =
334
+ exp = le[1].strip
335
+
336
+ #For CopyPage(original_page), page_var is original_page
337
+ #This only supports variable names at this time
338
+ exp.match /\((.*?),(.*)\);?/
339
+ page_var = $1
340
+ value_var = $2
341
+
342
+ out << %{
343
+ #{page_var}._next = #{value_var};
344
+ }
345
+
346
+ elsif l =~ /SetPageHead/
347
+ le = (l.split /SetPageHead/)
348
+ lvar = le[0].strip #Probably var x =
349
+ exp = le[1].strip
350
+
351
+ #For CopyPage(original_page), page_var is original_page
352
+ #This only supports variable names at this time
353
+ exp.match /\((.*?),(.*)\);?/
354
+ page_var = $1
355
+ value_var = $2
356
+
357
+ out << %{
358
+ #{page_var}._head = #{value_var};
359
+ }
360
+
361
+ elsif l =~ /EntryMutable/
362
+ le = (l.split /EntryMutable/)
363
+ lvar = le[0].strip #Probably var x =
364
+ exp = le[1].strip
365
+
366
+ #For CopyPage(original_page), page_var is original_page
367
+ #This only supports variable names at this time
368
+ exp.match /\((.*?),(.*)\);?/
369
+ page_var = $1
370
+ index_var = $2
371
+
372
+ out << %{
373
+ //Duplicate entry
374
+ #{page_var}.entries.splice(#{index_var}, 1, JSON.parse(JSON.stringify(#{page_var}.entries[#{index_var}])));
375
+ }
249
376
  else
250
377
  out.puts l
251
378
  end
data/lib/flok/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Flok
2
- VERSION = "0.0.38"
2
+ VERSION = "0.0.39"
3
3
  end
data/spec/env/kern.rb CHANGED
@@ -4,6 +4,10 @@ require './spec/lib/temp_dir'
4
4
 
5
5
  shared_context "kern" do
6
6
  before(:each) do
7
+ reset_for_ctx
8
+ end
9
+
10
+ def reset_for_ctx
7
11
  res=system('rake build:world')
8
12
  raise "Could not run build:world" unless res
9
13
  @ctx = V8::Context.new
@@ -15,6 +19,16 @@ shared_context "kern" do
15
19
  end
16
20
  end
17
21
 
22
+ class V8::Context
23
+ def dump variable
24
+ json_res = self.eval %{
25
+ JSON.stringify(#{variable});
26
+ }
27
+
28
+ return JSON.parse(json_res)
29
+ end
30
+ end
31
+
18
32
  #Execute flok binary with a command
19
33
  def flok args
20
34
  #Get path to the flok binary relative to this file
@@ -44,6 +58,7 @@ shared_context "kern" do
44
58
  #Execute
45
59
  @driver = FakeDriverContext.new
46
60
  v8 = V8::Context.new(:with => @driver)
61
+ @ctx = v8
47
62
  @driver.ctx = v8
48
63
  v8.eval %{
49
64
  //We must convert this to JSON because the fake driver will receive
@@ -74,6 +89,12 @@ shared_context "kern" do
74
89
  @q += JSON.parse(q)
75
90
  end
76
91
 
92
+ #When you're running these unit tests, you may need to log, but you will
93
+ #need to remove any _log statements before running other tests!
94
+ def log(msg)
95
+ $stderr.puts "v8: #{msg}"
96
+ end
97
+
77
98
  #Expect a certain message, with some arguments, and a certain priority
78
99
  #expect("if_init_view", ["test_view", {}]) === [[0, 4, "if_init_view", "test_view", {}]]
79
100
  def mexpect(msg_name, msg_args, priority=0)
@@ -96,6 +117,50 @@ shared_context "kern" do
96
117
  expect(priority).to eq(@cp)
97
118
  end
98
119
 
120
+ #Ignore all messages until this one is received, then keep that one in the queue
121
+ #There may be a lot going on and you're only interested in a part.
122
+ #If priority is nil, it won't matter what the priority is, useful for checking exceptions
123
+ #for non-existant messages
124
+ def ignore_up_to msg_name, priority=nil
125
+ @did_get = []
126
+
127
+ loop do
128
+ if @q.count == 0 and @cq.count == 0
129
+ raise "Waited for the message #{msg_name.inspect} but never got it... did get: \n * #{@did_get.join("\n * ")}"
130
+ end
131
+ #Dequeue from multi-priority queue if possible
132
+ if @cq.nil? or @cq.count == 0
133
+ @cq = @q.shift
134
+ @cp = @cq.shift #save priority
135
+ end
136
+
137
+ #Check to see if it's the correct item
138
+ arg_len = @cq.shift
139
+ name = @cq.shift
140
+ if arg_len.class == String
141
+ $stderr.puts "Arg len is: #{arg_len.inspect}"
142
+ $stderr.puts "Name is #{name.inspect}"
143
+ end
144
+ args = @cq.shift(arg_len)
145
+
146
+ @did_get << name
147
+
148
+ if name == msg_name
149
+ if priority
150
+ raise "Found the message #{msg_name.inspect} while calling ignore_up_to... but it's the wrong priority: #{@cp}, should be #{priority}" if @cp != priority
151
+ end
152
+
153
+ #Unshift everything in reverse order, we are only peeking here...
154
+ args.reverse.each do |a|
155
+ @cq.unshift a
156
+ end
157
+ @cq.unshift name
158
+ @cq.unshift arg_len
159
+ break
160
+ end
161
+ end
162
+ end
163
+
99
164
  #Retrieve a message, we at least expect a name and priority
100
165
  def get msg_name, priority=0
101
166
  #Dequeue from multi-priority queue if possible
@@ -129,5 +194,11 @@ shared_context "kern" do
129
194
  int_dispatch(#{msg});
130
195
  }
131
196
  end
197
+
198
+ def dump_q
199
+ q = @q
200
+ @q = []
201
+ return q
202
+ end
132
203
  end
133
204
  end
@@ -3,14 +3,9 @@ require './spec/env/etc.rb'
3
3
 
4
4
 
5
5
  RSpec.describe "macro" do
6
- before(:each) do
7
- macro_file = './app/kern/macro.rb'
8
- load macro_file
9
- end
10
-
11
6
  it "Changes the text when SEND exists" do
12
7
  original = 'SEND("main", "if_net_req", url, params, tp)'
13
- text = macro_process original
8
+ text = Flok.macro_process original
14
9
 
15
10
  expect(original).not_to eq(text)
16
11
  expect(text.class).to eq(String)
@@ -19,14 +14,14 @@ RSpec.describe "macro" do
19
14
 
20
15
  it "Has same # of lines with SEND" do
21
16
  original = 'SEND("main", "if_net_req", url, params, tp)'
22
- text = macro_process original
17
+ text = Flok.macro_process original
23
18
 
24
19
  expect(text.split("\n").length).to eq(original.split("\n").length)
25
20
  end
26
21
 
27
22
  it "encodes SEND correctly" do
28
23
  original = 'SEND("main", "if_net_req", url, params, tp)'
29
- text = macro_process original
24
+ text = Flok.macro_process original
30
25
 
31
26
  @arr = []
32
27
  expected_code = %{main_q.push([3, "if_net_req", url, params, tp])}
@@ -0,0 +1,27 @@
1
+ service :my_service do
2
+ on_wakeup %{
3
+ on_wakeup_called = '#{@options[:hello]}';
4
+ SEND("main", "if_event", 3, "action", {});
5
+ }
6
+
7
+ on_sleep %{
8
+ on_sleep_called = true;
9
+ }
10
+
11
+ on_connect %{
12
+ on_connect_called_bp = bp;
13
+ }
14
+
15
+ on_disconnect %{
16
+ on_disconnect_called_bp = bp;
17
+ }
18
+
19
+ on "hello", %{
20
+ on_hello_called_bp = bp;
21
+ on_hello_called_params = JSON.stringify(params);
22
+ }
23
+
24
+ every 5.seconds, %{
25
+ on_every_5_sec_called = true;
26
+ }
27
+ end