durable_rules 0.31.1

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.
@@ -0,0 +1,13 @@
1
+ /* Drop in replacement for zmalloc.h in order to just use libc malloc without
2
+ * any wrappering. */
3
+
4
+ #ifndef ZMALLOC_H
5
+ #define ZMALLOC_H
6
+
7
+ #define zmalloc malloc
8
+ #define zrealloc realloc
9
+ #define zcalloc(x) calloc(x,1)
10
+ #define zfree free
11
+ #define zstrdup strdup
12
+
13
+ #endif
data/librb/durable.rb ADDED
@@ -0,0 +1,549 @@
1
+ require_relative "engine"
2
+ require_relative "interface"
3
+
4
+ module Durable
5
+ @@rulesets = {}
6
+ @@start_blocks = []
7
+
8
+ def self.run(ruleset_definitions = nil, databases = [{:host => 'localhost', :port => 6379, :password => nil}], start = nil)
9
+ main_host = Engine::Host.new ruleset_definitions, databases
10
+ start.call main_host if start
11
+ main_host.start!
12
+ Interface::Application.set_host main_host
13
+ Interface::Application.run!
14
+ end
15
+
16
+ def self.run_all(databases = [{:host => 'localhost', :port => 6379, :password => nil}])
17
+ main_host = Engine::Host.new @@rulesets, databases
18
+ for block in @@start_blocks
19
+ main_host.instance_exec main_host, &block
20
+ end
21
+ main_host.start!
22
+ Interface::Application.set_host main_host
23
+ Interface::Application.run!
24
+ end
25
+
26
+ def self.ruleset(name, &block)
27
+ ruleset = Ruleset.new name, block
28
+ @@rulesets[name] = ruleset.rules
29
+ @@start_blocks << ruleset.start if ruleset.start
30
+ end
31
+
32
+ def self.statechart(name, &block)
33
+ statechart = Statechart.new name, block
34
+ @@rulesets[name.to_s + "$state"] = statechart.states
35
+ @@start_blocks << statechart.start if statechart.start
36
+ end
37
+
38
+ def self.flowchart(name, &block)
39
+ flowchart = Flowchart.new name, block
40
+ @@rulesets[name.to_s + "$flow"] = flowchart.stages
41
+ @@start_blocks << flowchart.start if flowchart.start
42
+ end
43
+
44
+ class Arithmetic
45
+
46
+ def initialize(name, left = nil, sid = nil, op = nil, right = nil)
47
+ @name = name
48
+ @left = left
49
+ @sid = sid
50
+ @right = right
51
+ @op = op
52
+ end
53
+
54
+ def definition
55
+ if not @op
56
+ if @sid
57
+ {@name => {:name => @left, :id => @sid}}
58
+ else
59
+ {@name => @left}
60
+ end
61
+ else
62
+ new_definition = nil
63
+ left_definition = nil
64
+ if @left.kind_of? Arithmetic
65
+ left_definition = @left.definition
66
+ else
67
+ left_definition = {@name => @left}
68
+ end
69
+
70
+ righ_definition = @right
71
+ if @right.kind_of? Arithmetic
72
+ righ_definition = @right.definition
73
+ end
74
+
75
+ return {@op => {:$l => left_definition, :$r => righ_definition}}
76
+ end
77
+ end
78
+
79
+ def +(other)
80
+ set_right(:$add, other)
81
+ end
82
+
83
+ def -(other)
84
+ set_right(:$sub, other)
85
+ end
86
+
87
+ def *(other)
88
+ set_right(:$mul, other)
89
+ end
90
+
91
+ def /(other)
92
+ set_right(:$div, other)
93
+ end
94
+
95
+ def ==(other)
96
+ return Expression.new(@name, @left) == other
97
+ end
98
+
99
+ def !=(other)
100
+ return Expression.new(@name, @left) != other
101
+ end
102
+
103
+ def <(other)
104
+ return Expression.new(@name, @left) < other
105
+ end
106
+
107
+ def <=(other)
108
+ return Expression.new(@name, @left) <= other
109
+ end
110
+
111
+ def >(other)
112
+ return Expression.new(@name, @left) > other
113
+ end
114
+
115
+ def >=(other)
116
+ return Expression.new(@name, @left) >= other
117
+ end
118
+
119
+ def -@
120
+ return -Expression.new(@name, @left)
121
+ end
122
+
123
+ def +@
124
+ return +Expression.new(@name, @left)
125
+ end
126
+
127
+ def |(other)
128
+ return Expression.new(@name, @left) | other
129
+ end
130
+
131
+ def &(other)
132
+ return Expression.new(@name, @left) & other
133
+ end
134
+
135
+ def id(sid)
136
+ Arithmetic.new @name, @left, sid
137
+ end
138
+
139
+ private
140
+
141
+ def set_right(op, other)
142
+ if @right
143
+ @left = Arithmetic.new @name, @left, @sid, @op, @right
144
+ end
145
+
146
+ @op = op
147
+ @right = other
148
+ self
149
+ end
150
+
151
+ def default(name, value=nil)
152
+ @left = name
153
+ self
154
+ end
155
+
156
+ alias method_missing default
157
+
158
+ end
159
+
160
+ class Expression
161
+ attr_reader :__type, :__op
162
+ attr_accessor :__name
163
+
164
+ def initialize(type, left = nil)
165
+ @__type = type
166
+ @left = left
167
+ @right = nil
168
+ @definitions = nil
169
+ @__name = nil
170
+ end
171
+
172
+ def definition
173
+ new_definition = nil
174
+ if @__op == :$or || @__op == :$and
175
+ new_definition = {@__op => @definitions}
176
+ else
177
+ if not @left
178
+ raise ArgumentError, "Property for #{@__op} not defined"
179
+ end
180
+ righ_definition = @right
181
+ if (@right.kind_of? Expression) || (@right.kind_of? Arithmetic)
182
+ righ_definition = @right.definition
183
+ end
184
+
185
+ if @__op == :$eq
186
+ new_definition = {@left => righ_definition}
187
+ else
188
+ new_definition = {@__op => {@left => righ_definition}}
189
+ end
190
+ end
191
+
192
+ if @__type == :$s
193
+ {:$and => [new_definition, {:$s => 1}]}
194
+ else
195
+ new_definition
196
+ end
197
+ end
198
+
199
+ def ==(other)
200
+ @__op = :$eq
201
+ @right = other
202
+ self
203
+ end
204
+
205
+ def !=(other)
206
+ @__op = :$neq
207
+ @right = other
208
+ self
209
+ end
210
+
211
+ def <(other)
212
+ @__op = :$lt
213
+ @right = other
214
+ self
215
+ end
216
+
217
+ def <=(other)
218
+ @__op = :$lte
219
+ @right = other
220
+ self
221
+ end
222
+
223
+ def >(other)
224
+ @__op = :$gt
225
+ @right = other
226
+ self
227
+ end
228
+
229
+ def >=(other)
230
+ @__op = :$gte
231
+ @right = other
232
+ self
233
+ end
234
+
235
+ def -@
236
+ @__op = :$nex
237
+ @right = 1
238
+ self
239
+ end
240
+
241
+ def +@
242
+ @__op = :$ex
243
+ @right = 1
244
+ self
245
+ end
246
+
247
+ def |(other)
248
+ merge other, :$or
249
+ self
250
+ end
251
+
252
+ def &(other)
253
+ merge other, :$and
254
+ self
255
+ end
256
+
257
+ private
258
+
259
+ def default(name, value=nil)
260
+ @left = name
261
+ self
262
+ end
263
+
264
+ def merge(other, op)
265
+ raise ArgumentError, "Right type doesn't match" if other.__type != @__type
266
+ @definitions = [self.definition] if !@definitions
267
+ @__op = op
268
+ if other.__op && (other.__op == @__op)
269
+ @definitions + other.definition[@__op]
270
+ else
271
+ @definitions << other.definition
272
+ end
273
+ end
274
+
275
+ alias method_missing default
276
+
277
+ end
278
+
279
+ class Expressions
280
+ attr_reader :__type
281
+
282
+ def initialize(type, expressions)
283
+ @__type = type
284
+ @expressions = expressions
285
+ end
286
+
287
+ def definition
288
+ index = 0
289
+ new_definition = []
290
+ for expression in @expressions do
291
+ if (expression.kind_of? Expression) && expression.__name
292
+ expression_name = expression.__name
293
+ elsif @expressions.length == 1
294
+ expression_name = "m"
295
+ else
296
+ expression_name = "m_#{index}"
297
+ end
298
+ if expression.__type == :$all
299
+ new_definition << {expression_name + "$all" => expression.definition()}
300
+ elsif expression.__type == :$any
301
+ new_definition << {expression_name + "$any" => expression.definition()}
302
+ elsif expression.__type == :$not
303
+ new_definition << {expression_name + "$not" => expression.definition()[0]["m"]}
304
+ else
305
+ new_definition << {expression_name => expression.definition()}
306
+ end
307
+ index += 1
308
+ end
309
+ new_definition
310
+ end
311
+
312
+ end
313
+
314
+ class Closure
315
+
316
+ def s
317
+ Arithmetic.new(:$s)
318
+ end
319
+
320
+ private
321
+
322
+ def handle_property(name, value=nil)
323
+ name = name.to_s
324
+ if name.end_with? '='
325
+ name = name[0..-2]
326
+ value.__name = name
327
+ return value
328
+ else
329
+ Arithmetic.new(name)
330
+ end
331
+ end
332
+
333
+ alias method_missing handle_property
334
+ end
335
+
336
+ class Ruleset
337
+ attr_reader :name, :start
338
+ attr_accessor :rules
339
+
340
+ def initialize(name, block)
341
+ @name = name
342
+ @rules = {}
343
+ @rule_index = 0
344
+ @expression_index = 0
345
+ @start = nil
346
+ self.instance_exec &block
347
+ end
348
+
349
+ def when_all(*args, &block)
350
+ options, new_args = get_options(*args)
351
+ define_rule :all, Expressions.new(:$all, new_args).definition, options, &block
352
+ end
353
+
354
+ def when_any(*args, &block)
355
+ options, new_args = get_options(*args)
356
+ define_rule :any, Expressions.new(:$any, new_args).definition, options, &block
357
+ end
358
+
359
+ def all(*args)
360
+ Expressions.new :$all, args
361
+ end
362
+
363
+ def any(*args)
364
+ Expressions.new :$any, args
365
+ end
366
+
367
+ def none(*args)
368
+ Expressions.new :$not, args
369
+ end
370
+
371
+ def when_start(&block)
372
+ @start = block
373
+ self
374
+ end
375
+
376
+ def s
377
+ Arithmetic.new(:$s)
378
+ end
379
+
380
+ def m
381
+ Expression.new(:$m)
382
+ end
383
+
384
+ def c
385
+ Closure.new()
386
+ end
387
+
388
+ def count(value)
389
+ {:count => value}
390
+ end
391
+
392
+ def pri(value)
393
+ {:pri => value}
394
+ end
395
+
396
+ def span(value)
397
+ {:span => value}
398
+ end
399
+
400
+ def cap(value)
401
+ {:cap => value}
402
+ end
403
+
404
+ def timeout(name)
405
+ expression = Expression.new(:$m, :$t)
406
+ expression == name
407
+ end
408
+
409
+ protected
410
+
411
+ def get_options(*args)
412
+ options = {}
413
+ new_args = []
414
+ for arg in args do
415
+ if arg.kind_of? Hash
416
+ options = options.merge!(arg)
417
+ else
418
+ new_args << arg
419
+ end
420
+ end
421
+ return options, new_args
422
+ end
423
+
424
+ def define_rule(operator, expression_definition, options, &block)
425
+ index = @rule_index.to_s
426
+ @rule_index += 1
427
+ rule_name = "r_#{index}"
428
+ rule = nil
429
+ if block
430
+ run_lambda = -> c {
431
+ c.instance_exec c, &block
432
+ }
433
+ rule = operator ? {operator => expression_definition, :run => run_lambda} : {:run => run_lambda}
434
+ else
435
+ rule = operator ? {operator => expression_definition} : {}
436
+ end
437
+
438
+ if options.key? :count
439
+ rule["count"] = options[:count]
440
+ end
441
+
442
+ if options.key? :pri
443
+ rule["pri"] = options[:pri]
444
+ end
445
+
446
+ if options.key? :span
447
+ rule["span"] = options[:span]
448
+ end
449
+
450
+ if options.key? :cap
451
+ rule["cap"] = options[:cap]
452
+ end
453
+
454
+ @rules[rule_name] = rule
455
+ rule
456
+ end
457
+
458
+ private
459
+
460
+ def handle_property(name, value=nil)
461
+ return Arithmetic.new(name.to_s)
462
+ end
463
+
464
+ alias method_missing handle_property
465
+
466
+ end
467
+
468
+
469
+ class State < Ruleset
470
+
471
+ def initialize(name, block)
472
+ super name, block
473
+ end
474
+
475
+ def to(state_name, rule = nil, &block)
476
+ rule = define_rule(nil, nil, {}, &block) if !rule
477
+ rule[:to] = state_name
478
+ if block
479
+ rule[:run] = -> s {s.instance_exec(s, &block)}
480
+ end
481
+ self
482
+ end
483
+
484
+ def state(state_name, &block)
485
+ @rules[:$chart] = {} if (!@rules.key? :$chart)
486
+ if block
487
+ @rules[:$chart][state_name] = State.new(state_name, block).rules
488
+ else
489
+ @rules[:$chart][state_name] = {}
490
+ end
491
+ end
492
+
493
+ end
494
+
495
+ class Statechart
496
+ attr_reader :states, :start
497
+
498
+ def initialize(name, block)
499
+ @states = {}
500
+ self.instance_exec &block
501
+ end
502
+
503
+ def state(state_name, &block)
504
+ if block
505
+ states[state_name] = State.new(state_name, block).rules
506
+ else
507
+ states[state_name] = {}
508
+ end
509
+ end
510
+
511
+ def when_start(&block)
512
+ @start = block
513
+ self
514
+ end
515
+
516
+ end
517
+
518
+ class Flowchart < Ruleset
519
+ attr_reader :stages
520
+
521
+ def initialize(name, block)
522
+ @stages = {}
523
+ @current_stage = nil
524
+ super name, block
525
+ end
526
+
527
+ def to(stage_name, rule = nil)
528
+ if !rule
529
+ stages[@current_stage][:to] = stage_name
530
+ elsif rule.key? :all
531
+ stages[@current_stage][:to][stage_name] = {:all => rule[:all]}
532
+ else
533
+ stages[@current_stage][:to][stage_name] = {:any => rule[:any]}
534
+ end
535
+ end
536
+
537
+ def stage(stage_name, &block)
538
+ if block
539
+ @stages[stage_name] = {:run => -> s {s.instance_exec(s, &block)}, :to => {}}
540
+ else
541
+ @stages[stage_name] = {:to => {}}
542
+ end
543
+
544
+ @current_stage = stage_name
545
+ self
546
+ end
547
+ end
548
+
549
+ end