divine 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +30 -0
  2. data/README.md +57 -0
  3. data/Rakefile +45 -18
  4. data/lib/divine.rb +3 -3
  5. data/lib/divine/code_generators/code_generator.rb +112 -14
  6. data/lib/divine/code_generators/java.rb +144 -80
  7. data/lib/divine/code_generators/javascript.rb +192 -104
  8. data/lib/divine/code_generators/ruby.rb +133 -60
  9. data/lib/divine/dsl.rb +70 -12
  10. data/lib/divine/version.rb +1 -1
  11. data/test/basic_complex_test/js_test/js_testBasic.js +1 -1
  12. data/test/basic_complex_test/js_test/js_testComplex.js +1 -1
  13. data/test/basic_complex_test/ruby_test/ruby_test.rb +10 -10
  14. data/test/binaryTree_test/js_test/js_test.js +1 -1
  15. data/test/binaryTree_test/ruby_test/ruby_test.rb +4 -4
  16. data/test/complex_test/js_test/js_test.js +3 -2
  17. data/test/ipv6_test/java_test/JavaTest.java +4 -6
  18. data/test/ipv6_test/js_test/js_test.js +1 -1
  19. data/test/signed_float_test/ruby_test/ruby_test.rb +36 -0
  20. data/test/signed_float_test/signed_float_test.rb +14 -0
  21. data/test/signed_int_test/java_test/JavaTest.java +83 -0
  22. data/test/signed_int_test/js_test/js_test.js +55 -0
  23. data/test/signed_int_test/ruby_test/ruby_test.rb +37 -0
  24. data/test/signed_int_test/signed_int_test.rb +15 -0
  25. data/test/unify_test/unify_test.rb +24 -13
  26. metadata +14 -38
  27. data/test/basic_complex_test/java_test/test_babel.java +0 -368
  28. data/test/basic_complex_test/js_test/test_babel.js +0 -523
  29. data/test/basic_complex_test/ruby_test/test_babel.rb +0 -368
  30. data/test/binaryTree_test/java_test/test_binaryTree.java +0 -301
  31. data/test/binaryTree_test/js_test/test_binaryTree.js +0 -447
  32. data/test/binaryTree_test/ruby_test/test_binaryTree.rb +0 -303
  33. data/test/complex_test/java_test/test_complex.java +0 -331
  34. data/test/complex_test/js_test/test_complex.js +0 -478
  35. data/test/complex_test/ruby_test/test_complex.rb +0 -330
  36. data/test/ipv6_test/java_test/junit.jar +0 -0
  37. data/test/ipv6_test/java_test/test_ipv6.java +0 -270
  38. data/test/ipv6_test/js_test/test_ipv6.js +0 -409
  39. data/test/ipv6_test/ruby_test/test_ipv6.rb +0 -267
  40. data/test/unify_test/java_test/test_unify.java +0 -171
  41. data/test/unify_test/js_test/js_test.js +0 -56
  42. data/test/unify_test/js_test/test_unify.js +0 -326
  43. data/test/unify_test/ruby_test/ruby_test.rb +0 -35
  44. data/test/unify_test/ruby_test/test_unify.rb +0 -187
@@ -1,6 +1,12 @@
1
1
  module Divine
2
2
 
3
3
  class RubyHelperMethods < BabelHelperMethods
4
+ def get_header_comment
5
+ get_header_comment_text.map do |s|
6
+ "# #{s}"
7
+ end.join("\n")
8
+ end
9
+
4
10
  def ruby_base_class_template_str
5
11
  %q{
6
12
  class BabelBase<%= toplevel_class %>
@@ -29,6 +35,24 @@ module Divine
29
35
  (data.getbyte << 24) | read_int24(data)
30
36
  end
31
37
 
38
+ def read_sint32(data)
39
+ max = (2** (32 - 1)) - 1
40
+ num = (data.getbyte << 24) | read_int24(data)
41
+ if num > max
42
+ return num - 2** 32
43
+ end
44
+ return num
45
+ end
46
+
47
+ def read_sint64(data)
48
+ max = (2** (64 - 1)) - 1
49
+ num = (read_int32(data) << 32) | (read_int32(data) & 0xFFFFFFFF);
50
+ if num > max
51
+ return num - 2** 64
52
+ end
53
+ return num
54
+ end
55
+
32
56
  def read_bool(data)
33
57
  read_int8(data) == 1
34
58
  end
@@ -107,6 +131,26 @@ module Divine
107
131
  write_int24( v & 0xFFFFFF, out)
108
132
  end
109
133
 
134
+ def write_sint32(v, out)
135
+ v = v.to_i
136
+ max = (2** (32 - 1)) - 1
137
+ min = (2** (32 - 1) ) - (2** 32)
138
+ raise_error "Too large Sint32 number: #{v} , Max = #{max}" if v > max # Max 2.147.483.647
139
+ raise_error "Too small sInt32 number: #{v} , Min = #{min}" if v < min # Min -2.147.483.648
140
+ write_int8( v >> 24 & 0xFF, out)
141
+ write_int24( v & 0xFFFFFF, out)
142
+ end
143
+
144
+ def write_sint64(v, out)
145
+ v = v.to_i
146
+ max = (2** (64 - 1)) - 1
147
+ min = (2** (64 - 1) ) - (2** 64)
148
+ raise_error "Too large Sint32 number: #{v} , Max = #{max}" if v > max # Max 2.147.483.647
149
+ raise_error "Too small sInt32 number: #{v} , Min = #{min}" if v < min # Min -2.147.483.648
150
+ write_int32( v >> 32 & 0xFFFFFFFF, out)
151
+ write_int32( v & 0xFFFFFFFF, out)
152
+ end
153
+
110
154
  def write_bool(v, out)
111
155
  write_int8(v ? 1 : 0, out)
112
156
  end
@@ -236,50 +280,99 @@ module Divine
236
280
  }
237
281
  end
238
282
 
239
- def ruby_class_template_str
240
- %q{
241
- class <%= c.name %> < BabelBase
242
- <% unless c.fields.empty? %>
243
- attr_accessor <%= c.fields.map { |x| ":#{x.name}" }.join(', ') %>
244
-
245
- def initialize()
246
- super
247
- <% c.fields.each do |f| %>
248
- @<%= f.name %> ||= <%= this.ruby_get_empty_declaration(f) %>
249
- <% end %>
250
- end
251
- <% end %>
252
-
253
- def serialize_internal(out)
254
- print "+"
255
- <% c.simple_fields.each do |f| %>
256
- write_<%= f.type %>(<%= f.name %>, out)
257
- <% end %>
258
- <% c.complex_fields.each do |f| %>
259
- <%= this.ruby_serialize_complex f %>
260
- <% end %>
261
- end
262
-
263
- def deserialize(data)
264
- print "-"
265
- <% c.simple_fields.each do |f| %>
266
- @<%= f.name %> = read_<%= f.type %>(data)
267
- <% end %>
268
- <% c.complex_fields.each do |f| %>
269
- <%= this.ruby_deserialize_complex f %>
270
- <% end %>
271
- end
272
- end
273
- }
283
+ def ruby_class_template(sh)
284
+ code = [
285
+ "class #{sh.name} < BabelBase",
286
+ :indent,
287
+ "",
288
+
289
+ # PROPERTIES
290
+ if sh.field_names.size > 0
291
+ "attr_accessor :struct_version, #{sh.field_names.map {|n| ":#{n}" }.join(', ')}"
292
+ else
293
+ "attr_accessor :struct_version"
294
+ end, "",
295
+
296
+
297
+ # INITIALIZE
298
+ "def initialize()",
299
+ :indent,
300
+ "super",
301
+ "@struct_version ||= #{sh.latest_version}",
302
+ sh.field_names.map do |fn|
303
+ "@#{fn} ||= #{ruby_get_empty_declaration(sh.field(fn).first)}"
304
+ end,
305
+ :deindent,
306
+ "end", "",
307
+
308
+ # SERiALIZE INTERNAL
309
+ "def serialize_internal(out)",
310
+ :indent,
311
+ "write_int8(@struct_version, out)",
312
+ sh.structs.map do |s|
313
+ [
314
+ "if @struct_version == #{s.version}",
315
+ :indent,
316
+ s.simple_fields.map do |f|
317
+ "write_#{f.type}(#{f.name}, out)"
318
+ end,
319
+ s.complex_fields.map do |f|
320
+ [
321
+ "", "# Serialize #{f.type} '#{f.name}'",
322
+ ruby_serialize_internal(f.name, f.referenced_types)
323
+ ]
324
+ end,
325
+ "return",
326
+ :deindent,
327
+ "end", ""
328
+ ]
329
+ end, "",
330
+ "raise \"Unsupported version #\{@struct_version\} for type '#{sh.name}'\"",
331
+ :deindent,
332
+ "end", "",
333
+
334
+ # DESERIALIZE
335
+ "def deserialize(data)",
336
+ :indent,
337
+ "@struct_version = read_int8(data)",
338
+ sh.structs.map do |s|
339
+ [
340
+ "if @struct_version == #{s.version}",
341
+ :indent,
342
+ s.simple_fields.map do |f|
343
+ "@#{f.name} = read_#{f.type}(data)"
344
+ end,
345
+ s.complex_fields.map do |f|
346
+ [
347
+ "", "# Read #{f.type} '#{f.name}'",
348
+ ruby_deserialize_internal("@#{f.name}", f.referenced_types)
349
+ ]
350
+ end,
351
+ "return",
352
+ :deindent,
353
+ "end"
354
+ ]
355
+ end, "",
356
+ "raise \"Unsupported version #\{@struct_version\} for type '#{sh.name}'\"",
357
+ :deindent,
358
+ "end", "",
359
+
360
+
361
+ # END OF CLASS
362
+ :deindent,
363
+ "end"
364
+ ]
365
+ format_src(0, 3, code)
274
366
  end
275
367
 
368
+
276
369
  def ruby_get_empty_declaration(field)
277
370
  case field.type
278
371
  when :list, :binary, :short_binary
279
372
  "[]"
280
373
  when :map
281
374
  "{}"
282
- when :int8, :int16, :int32
375
+ when :int8, :int16, :int32, :sint32, :sint64
283
376
  "0"
284
377
  when :string, :ip_number
285
378
  "\"\""
@@ -288,15 +381,6 @@ module Divine
288
381
  end
289
382
  end
290
383
 
291
- def ruby_serialize_complex(field)
292
- types = field.referenced_types
293
- as = [
294
- "# Serialize #{field.type} '#{field.name}'",
295
- ruby_serialize_internal(field.name, types)
296
- ]
297
- format_src(6, 3, as)
298
- end
299
-
300
384
  def ruby_serialize_internal(var, types)
301
385
  if types.respond_to? :first
302
386
  case types.first
@@ -338,15 +422,6 @@ module Divine
338
422
  end
339
423
  end
340
424
 
341
- def ruby_deserialize_complex(field)
342
- types = field.referenced_types
343
- as = [
344
- "# Deserialize #{field.type} '#{field.name}'",
345
- ruby_deserialize_internal("@#{field.name}", types)
346
- ]
347
- format_src(6, 3, as)
348
- end
349
-
350
425
  def ruby_deserialize_internal(var, types)
351
426
  if types.respond_to? :first
352
427
  case types.first
@@ -406,21 +481,19 @@ module Divine
406
481
  @debug = true
407
482
 
408
483
  def generate_code(structs, opts)
409
- pp opts
410
484
  base_template = Erubis::Eruby.new(ruby_base_class_template_str)
411
- class_template = Erubis::Eruby.new(ruby_class_template_str)
412
485
  keys = structs.keys.sort
413
486
  src = keys.map do |k|
414
487
  ss = structs[k]
415
- # TODO: Should we merge different versions and deduce deprecated methods, warn for incompatible changes, etc?
416
- raise "Duplicate definitions of struct #{k}" if ss.size > 1
417
- class_template.result( c: ss.first, this: self )
488
+ # Check different aspects the the structs
489
+ vss = sanity_check(ss)
490
+ ruby_class_template(StructHandler.new(vss))
418
491
  end
419
492
 
420
493
  # User defined super class?
421
494
  toplevel = opts[:parent_class] || nil
422
495
  toplevel = " < #{toplevel}" if toplevel
423
- return [{file: opts[:file], src: "#{ruby_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel })}\n\n#{src.join("\n\n")}#{ruby_get_end_module(opts)}"}]
496
+ return [{file: opts[:file], src: "#{get_header_comment}\n#{ruby_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel, this: self })}\n\n#{src.join("\n\n")}#{ruby_get_end_module(opts)}"}]
424
497
  end
425
498
 
426
499
  def ruby_get_begin_module(opts)
@@ -2,7 +2,8 @@ module Divine
2
2
  $all_structs = {}
3
3
 
4
4
  class StructDefinition
5
- def initialize(type, args)
5
+ def initialize(owner, type, args)
6
+ @owner = owner
6
7
  @type = type
7
8
  @args = args
8
9
  end
@@ -14,12 +15,20 @@ module Divine
14
15
  def type
15
16
  @type
16
17
  end
18
+
19
+ def version
20
+ @owner.version
21
+ end
22
+
23
+ def to_s
24
+ "#{@owner.name}: #{self.type} #{self.name} (#{self.class.name}, #{@args.inspect})"
25
+ end
17
26
  end
18
27
 
19
28
  class SimpleDefinition < StructDefinition
20
29
  def simple?; true; end
21
30
  def referenced_types
22
- @type
31
+ [@type]
23
32
  end
24
33
  end
25
34
 
@@ -39,6 +48,12 @@ module Divine
39
48
  end
40
49
  end
41
50
 
51
+ class SInteger64Definition < SimpleDefinition
52
+ end
53
+
54
+ class SInteger32Definition < SimpleDefinition
55
+ end
56
+
42
57
  class Integer32Definition < SimpleDefinition
43
58
  end
44
59
 
@@ -84,6 +99,8 @@ module Divine
84
99
 
85
100
 
86
101
  $available_types = {
102
+ sint64: SInteger64Definition,
103
+ sint32: SInteger32Definition,
87
104
  int32: Integer32Definition,
88
105
  int24: Integer24Definition,
89
106
  int16: Integer16Definition,
@@ -102,10 +119,10 @@ module Divine
102
119
  # Name = name of the struct
103
120
  # Version = struct version (not currently used)
104
121
  # Fields = All defined fields
105
- attr_reader :name, :version, :fields
122
+ attr_reader :name, :properties, :fields
106
123
 
107
- def initialize(name, version)
108
- @version = version
124
+ def initialize(name, ps)
125
+ @properties = ps
109
126
  @name = name.to_sym
110
127
  @fields = []
111
128
  unless @name == :_inline_
@@ -114,35 +131,76 @@ module Divine
114
131
  end
115
132
  end
116
133
 
134
+ #
135
+ # Get the version of the struct
136
+ #
137
+ def version
138
+ if properties && properties[:version]
139
+ properties[:version].to_i
140
+ else
141
+ 1
142
+ end
143
+ rescue => e
144
+ raise "Failed to get version number from '#{name}': #{properties.inspect}\n#{e}"
145
+ end
146
+
147
+ #
148
+ # Is the struct freezed? I.e. no changes are allowed
149
+ #
150
+ def freezed?
151
+ nil != freeze_signature
152
+ end
153
+
154
+ #
155
+ # Get the freeze signature
156
+ #
157
+ def freeze_signature
158
+ if properties && properties[:freeze]
159
+ properties[:freeze]
160
+ else
161
+ nil
162
+ end
163
+ end
164
+
117
165
  #
118
166
  # Get all simple fields, i.e. basic types like string, etc
119
167
  #
120
168
  def simple_fields
121
- fields.select(&:simple?)
169
+ fields.select(&:simple?)
122
170
  end
123
171
 
124
172
  #
125
173
  # Get all complex fields, i.e. lists and hashmaps
126
174
  #
127
175
  def complex_fields
128
- fields.reject(&:simple?)
176
+ fields.reject(&:simple?)
177
+ end
178
+
179
+ #
180
+ # Get named field
181
+ #
182
+ def get_field(name)
183
+ fields.each do |f|
184
+ return f if f.name == name
185
+ end
186
+ return nil
129
187
  end
130
188
 
131
189
  def method_missing(m, *args, &block)
132
- puts "... #{m}"
190
+ #puts "... #{m} #{args.inspect}"
133
191
  type = $available_types[m]
134
192
  if type
135
193
  if block_given?
136
- puts ".... recursive definition"
137
- builder = StructBuilder.new(:_inline_, version)
194
+ #puts ".... recursive definition"
195
+ builder = StructBuilder.new(:_inline_, args)
138
196
  Docile.dsl_eval(builder, &block)
139
197
  args << builder
140
198
  end
141
199
  if @name == :_inline_
142
200
  # Pad the _inline_ name to anonymous inner types
143
- @fields << type.new(m, [@name] + args)
201
+ @fields << type.new(self, m, [@name] + args)
144
202
  else
145
- @fields << type.new(m, args)
203
+ @fields << type.new(self, m, args)
146
204
  end
147
205
  #puts "... adding #{m} to #{name}, got #{fields} ..."
148
206
  else
@@ -1,3 +1,3 @@
1
1
  module Divine
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -18,7 +18,7 @@ var read = deserialize();
18
18
 
19
19
 
20
20
  var testBasic_deser = new TestBasic();
21
- testBasic_deser.deserialize(new BabelDataReader(read));
21
+ testBasic_deser.deserialize(new DivineDataReader(read));
22
22
 
23
23
  assert.equal(testBasic_ser.i8, testBasic_deser.i8);
24
24
  assert.equal(testBasic_ser.i16, testBasic_deser.i16);
@@ -16,7 +16,7 @@ serialize(ca);
16
16
  var read = deserialize();
17
17
 
18
18
  var testComplex_deser = new TestComplex();
19
- testComplex_deser.deserialize(new BabelDataReader(read));
19
+ testComplex_deser.deserialize(new DivineDataReader(read));
20
20
 
21
21
  compare_list(testComplex_ser.list1, testComplex_deser.list1);
22
22
  compare_list(testComplex_ser.list2, testComplex_deser.list2);
@@ -24,12 +24,12 @@ class TestBabelTestBasic < MiniTest::Unit::TestCase
24
24
  testbasic_deser = BabelTest::TestBasic.new
25
25
  testbasic_deser.deserialize res
26
26
 
27
- assert testbasic_ser.i8 == testbasic_deser.i8
28
- assert testbasic_ser.i16 == testbasic_deser.i16
29
- assert testbasic_ser.i32 == testbasic_deser.i32
30
- assert testbasic_ser.str == testbasic_deser.str
31
- assert testbasic_ser.ip == testbasic_deser.ip
32
- assert testbasic_ser.guid == testbasic_deser.guid
27
+ assert_equal testbasic_ser.i8 , testbasic_deser.i8
28
+ assert_equal testbasic_ser.i16 , testbasic_deser.i16
29
+ assert_equal testbasic_ser.i32 , testbasic_deser.i32
30
+ assert_equal testbasic_ser.str , testbasic_deser.str
31
+ assert_equal testbasic_ser.ip , testbasic_deser.ip
32
+ assert_equal testbasic_ser.guid , testbasic_deser.guid
33
33
  end
34
34
 
35
35
  def test_complex
@@ -48,11 +48,11 @@ class TestBabelTestBasic < MiniTest::Unit::TestCase
48
48
  testcomplex_deser = BabelTest::TestComplex.new
49
49
  testcomplex_deser.deserialize res
50
50
 
51
- assert testcomplex_ser.list1.sort == testcomplex_deser.list1.sort
52
- assert testcomplex_ser.list2.sort == testcomplex_deser.list2.sort
53
- assert testcomplex_ser.map1 == testcomplex_deser.map1
51
+ assert_equal testcomplex_ser.list1, testcomplex_deser.list1
52
+ assert_equal testcomplex_ser.list2, testcomplex_deser.list2
53
+ assert_equal testcomplex_ser.map1, testcomplex_deser.map1
54
54
  testcomplex_ser.map2.keys.each do |k|
55
- assert testcomplex_ser.map2[k].length == testcomplex_deser.map2[k].length
55
+ assert_equal testcomplex_ser.map2[k].length, testcomplex_deser.map2[k].length
56
56
  end
57
57
  end
58
58