divine 0.0.3 → 0.0.4
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/.gitignore +4 -14
- data/README.md +25 -0
- data/Rakefile +34 -19
- data/divine.gemspec +1 -0
- data/lib/divine.rb +3 -1
- data/lib/divine/code_generators/code_generator.rb +51 -1
- data/lib/divine/code_generators/csharp.rb +898 -0
- data/lib/divine/code_generators/java.rb +125 -13
- data/lib/divine/code_generators/javascript.rb +111 -4
- data/lib/divine/code_generators/ruby.rb +103 -9
- data/lib/divine/dsl.rb +95 -6
- data/lib/divine/graph_generator/graph_generator.rb +81 -0
- data/lib/divine/version.rb +2 -1
- data/test/basic_complex_test/basic_complex_test.rb +5 -0
- data/test/basic_complex_test/graph.jpg +0 -0
- data/test/basic_complex_test/java_test/JavaTest.java +1 -1
- data/test/basic_complex_test/ruby_test/ruby_test.rb +17 -4
- data/test/binaryTree_test/binaryTree_test.rb +5 -0
- data/test/binaryTree_test/csharp_test/csharp_test.cs +99 -0
- data/test/binaryTree_test/graph.png +0 -0
- data/test/binaryTree_test/java_test/JavaTest.java +1 -1
- data/test/binaryTree_test/ruby_test/ruby_test.rb +26 -3
- data/test/complex_test/complex_test.rb +5 -0
- data/test/complex_test/csharp_test/csharp_test.cs +109 -0
- data/test/complex_test/graph.png +0 -0
- data/test/complex_test/java_test/JavaTest.java +1 -1
- data/test/complex_test/ruby_test/ruby_test.rb +24 -1
- data/test/dynamic_int_test/csharp_test/csharp_test.cs +76 -0
- data/test/dynamic_int_test/dynamic_int_test.rb +20 -0
- data/test/dynamic_int_test/graph.jpg +0 -0
- data/test/dynamic_int_test/java_test/JavaTest.java +72 -0
- data/test/dynamic_int_test/js_test/js_test.js +54 -0
- data/test/dynamic_int_test/ruby_test/ruby_test.rb +55 -0
- data/test/ipv6_test/csharp_test/csharp_test.cs +73 -0
- data/test/ipv6_test/graph.jpg +0 -0
- data/test/ipv6_test/ipv6_test.rb +5 -0
- data/test/ipv6_test/java_test/JavaTest.java +1 -1
- data/test/ipv6_test/ruby_test/ruby_test.rb +24 -4
- data/test/lib/csharp/nunit.framework.dll +0 -0
- data/test/{java_lib → lib/java}/junit.jar +0 -0
- data/test/signed_int_test/csharp_test/csharp_test.cs +86 -0
- data/test/signed_int_test/graph.jpg +0 -0
- data/test/signed_int_test/java_test/JavaTest.java +1 -1
- data/test/signed_int_test/ruby_test/ruby_test.rb +21 -1
- data/test/signed_int_test/signed_int_test.rb +6 -0
- data/test/unify_test/unify_test.rb +17 -4
- metadata +54 -8
- data/test/signed_float_test/ruby_test/ruby_test.rb +0 -36
- data/test/signed_float_test/signed_float_test.rb +0 -14
@@ -1,15 +1,32 @@
|
|
1
1
|
module Divine
|
2
2
|
|
3
|
+
##
|
4
|
+
# * +Java Helper+ :
|
5
|
+
# Support base function needed to build Divine enviroment and classes corresponding to DSL structs
|
6
|
+
#
|
3
7
|
class JavaHelperMethods < BabelHelperMethods
|
8
|
+
|
9
|
+
#
|
10
|
+
# Return the header comment
|
11
|
+
#
|
4
12
|
def get_header_comment
|
5
13
|
get_header_comment_text.map do |s|
|
6
14
|
"// #{s}"
|
7
15
|
end.join("\n")
|
8
16
|
end
|
9
17
|
|
18
|
+
##
|
19
|
+
# Generate the base Divine Java Class
|
20
|
+
# that contains the main methods:
|
21
|
+
# * serialize
|
22
|
+
# * serialize Internal
|
23
|
+
# * deserialize
|
24
|
+
# * Read Methods
|
25
|
+
# * Write Methods
|
26
|
+
|
10
27
|
def java_base_class_template_str
|
11
28
|
<<EOS
|
12
|
-
abstract class
|
29
|
+
abstract class Divine <%= toplevel_class %> {
|
13
30
|
private static final Charset UTF8 = Charset.forName("UTF-8");
|
14
31
|
|
15
32
|
public byte[] serialize() throws IOException {
|
@@ -47,6 +64,17 @@ abstract class BabelBase <%= toplevel_class %> {
|
|
47
64
|
return (readInt32(data) << 32) | (readInt32(data) & 0xFFFFFFFFL);
|
48
65
|
}
|
49
66
|
|
67
|
+
protected long readDint63(ByteArrayInputStream data) {
|
68
|
+
int b = readInt8(data);
|
69
|
+
long val = b & 0x7F;
|
70
|
+
while((b >> 7) == 1){
|
71
|
+
b = readInt8(data);
|
72
|
+
val = val << 7;
|
73
|
+
val = val | b & 0x7F;
|
74
|
+
}
|
75
|
+
return val;
|
76
|
+
}
|
77
|
+
|
50
78
|
protected boolean readBool(ByteArrayInputStream data) {
|
51
79
|
return readInt8(data) == 1;
|
52
80
|
}
|
@@ -161,14 +189,30 @@ abstract class BabelBase <%= toplevel_class %> {
|
|
161
189
|
|
162
190
|
protected void writeSint64(long v, ByteArrayOutputStream out) {
|
163
191
|
if (v > Long.MAX_VALUE) { // Max 9,223,372,036,854,775,807
|
164
|
-
raiseError("Too large sInt64 number: " + v + ", Max = " +
|
165
|
-
}else if(v < Long.MIN_VALUE){ // Min -9,223,372,036,854,775,
|
166
|
-
raiseError("Too small sInt64 number: " + v + ", Min = " +
|
192
|
+
raiseError("Too large sInt64 number: " + v + ", Max = " + Long.MAX_VALUE);
|
193
|
+
}else if(v < Long.MIN_VALUE){ // Min -9,223,372,036,854,775,808
|
194
|
+
raiseError("Too small sInt64 number: " + v + ", Min = " + Long.MIN_VALUE);
|
167
195
|
}
|
168
196
|
writeInt32(((v >> 32) & 0xFFFFFFFFL), out);
|
169
197
|
writeInt32( (v & 0xFFFFFFFFL) , out);
|
170
198
|
}
|
171
199
|
|
200
|
+
protected void writeDint63(long v, ByteArrayOutputStream out) {
|
201
|
+
if (v > Long.MAX_VALUE) { // Max 9,223,372,036,854,775,807
|
202
|
+
raiseError("Too large Dynamic Int64 number: " + v + ", Max = " + Long.MAX_VALUE);
|
203
|
+
}else if(v < 0){ // Min 0
|
204
|
+
raiseError("Too small Dynamic Int64 number: " + v + ", Min = " + 0);
|
205
|
+
}
|
206
|
+
String[] bytes = new StringBuffer(Long.toBinaryString(v)).reverse().toString().split("(?<=\\\\G.......)");
|
207
|
+
|
208
|
+
for (int i = bytes.length - 1; i >= 0; i--){
|
209
|
+
String s = bytes[i];
|
210
|
+
s += new String(new char[7 - s.length()]).replace("\\\\0", "0") + Math.min(i, 1);
|
211
|
+
int t = Integer.parseInt(new StringBuffer(s).reverse().toString(), 2);
|
212
|
+
this.writeInt8(t, out);
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
172
216
|
protected void writeBool(boolean v, ByteArrayOutputStream out) {
|
173
217
|
writeInt8(v ? 1 : 0, out);
|
174
218
|
}
|
@@ -276,9 +320,13 @@ abstract class BabelBase <%= toplevel_class %> {
|
|
276
320
|
EOS
|
277
321
|
end
|
278
322
|
|
323
|
+
##
|
324
|
+
# Generate Java Class that corresponding to the struct definition
|
325
|
+
# * *Args* :
|
326
|
+
# - +sh+ -> Struct Name
|
279
327
|
def java_class_template(sh)
|
280
328
|
code = [
|
281
|
-
"class #{sh.name} extends
|
329
|
+
"class #{sh.name} extends Divine {",
|
282
330
|
:indent,
|
283
331
|
"",
|
284
332
|
|
@@ -354,6 +402,30 @@ EOS
|
|
354
402
|
format_src(3, 3, code)
|
355
403
|
end
|
356
404
|
|
405
|
+
##
|
406
|
+
# Generate default java data types declaration values corresponding to each DSL types:
|
407
|
+
# * DSL Type --> Corresponding Default Java Value
|
408
|
+
# * dint63 --> 0 range -> [0 - 9,223,372,036,854,775,807]
|
409
|
+
# * 1 byte: range -> [0 - 127]
|
410
|
+
# * 2 bytes: range -> [0 - 16,383]
|
411
|
+
# * 3 bytes: range -> [0 - 2,097,151]
|
412
|
+
# * 4 bytes: range -> [0 - 268,435,455]
|
413
|
+
# * 5 bytes: range -> [0 - 34,359,738,367]
|
414
|
+
# * 6 bytes: range -> [0 - 4,398,046,511,103]
|
415
|
+
# * 7 bytes: range -> [0 - 562,949,953,421,311]
|
416
|
+
# * 8 bytes: range -> [0 - 72,057,594,037,927,935]
|
417
|
+
# * 9 bytes: range -> [0 - 9,223,372,036,854,775,807]
|
418
|
+
# * int8 --> 0 Range -> [0 - 255]
|
419
|
+
# * int16 --> 0 Range -> [0 - 65535]
|
420
|
+
# * int32 --> 0L Range -> [0 - 4.294.967.295]
|
421
|
+
# * sint32 --> 0 Range -> [-2.147.483.648 - 2.147.483.647]
|
422
|
+
# * sint64 --> 0L Range -> [-9.223.372.036.854.775.808, 9.223.372.036.854.775.807]
|
423
|
+
# * string --> ""
|
424
|
+
# * ip_number--> ""
|
425
|
+
# * binary --> new Byte[0]
|
426
|
+
# * short_binary --> new Byte[0]
|
427
|
+
# * list --> new ArrayList<type>()
|
428
|
+
# * map --> new HashMap<keyType, valueType>()
|
357
429
|
|
358
430
|
def java_get_empty_declaration(types, is_reference_type = false)
|
359
431
|
if types.respond_to? :referenced_types
|
@@ -378,7 +450,7 @@ EOS
|
|
378
450
|
is_reference_type ? "new Byte[0]" : "new byte[0]"
|
379
451
|
when :int8, :int16, :sint32
|
380
452
|
"0"
|
381
|
-
when :int32, :sint64
|
453
|
+
when :int32, :sint64, :dint63
|
382
454
|
"0L"
|
383
455
|
when :string, :ip_number
|
384
456
|
"\"\""
|
@@ -391,7 +463,23 @@ EOS
|
|
391
463
|
end
|
392
464
|
end
|
393
465
|
end
|
394
|
-
|
466
|
+
|
467
|
+
##
|
468
|
+
# Generate java data types declaration corresponding to each DSL type
|
469
|
+
# * DSL Type --> Corresponding Java Type
|
470
|
+
# * int8 --> int
|
471
|
+
# * int16 --> int
|
472
|
+
# * sint32 --> int
|
473
|
+
# * int32 --> long
|
474
|
+
# * sint64 --> long
|
475
|
+
# * dint63 --> long
|
476
|
+
# * string --> String
|
477
|
+
# * ip_number--> String
|
478
|
+
# * binary --> Byte[]
|
479
|
+
# * short_binary --> Byte[]
|
480
|
+
# * list --> ArrayList<type>
|
481
|
+
# * map --> HashMap<keyType, valueType>
|
482
|
+
|
395
483
|
def java_get_type_declaration(types, is_reference_type = false)
|
396
484
|
if types.respond_to? :referenced_types
|
397
485
|
java_get_type_declaration(types.referenced_types, is_reference_type)
|
@@ -418,7 +506,7 @@ EOS
|
|
418
506
|
is_reference_type ? "Byte[]" : "byte[]"
|
419
507
|
when :int8, :int16, :sint32
|
420
508
|
is_reference_type ? "Integer" : "int"
|
421
|
-
when :int32, :sint64
|
509
|
+
when :int32, :sint64, :dint63
|
422
510
|
is_reference_type ? "Long" : "long"
|
423
511
|
when :string, :ip_number
|
424
512
|
"String"
|
@@ -431,7 +519,12 @@ EOS
|
|
431
519
|
end
|
432
520
|
end
|
433
521
|
end
|
434
|
-
|
522
|
+
|
523
|
+
##
|
524
|
+
# Generate the way of serializing different DSL types
|
525
|
+
# * *Args* :
|
526
|
+
# - +var+ -> variable name
|
527
|
+
# - +types+ -> variable type
|
435
528
|
def java_serialize_internal(var, types)
|
436
529
|
if types.respond_to? :first
|
437
530
|
case types.first
|
@@ -476,6 +569,11 @@ EOS
|
|
476
569
|
end
|
477
570
|
end
|
478
571
|
|
572
|
+
##
|
573
|
+
# Generate the way of deserializing different DSL types
|
574
|
+
# * *Args* :
|
575
|
+
# - +var+ -> variable name
|
576
|
+
# - +types+ -> variable type
|
479
577
|
def java_deserialize_internal(var, types)
|
480
578
|
if types.respond_to? :first
|
481
579
|
case types.first
|
@@ -531,8 +629,16 @@ EOS
|
|
531
629
|
end
|
532
630
|
end
|
533
631
|
|
534
|
-
|
632
|
+
##
|
633
|
+
# Responsible for generating Divine and structs classes
|
634
|
+
#
|
535
635
|
class JavaGenerator < JavaHelperMethods
|
636
|
+
|
637
|
+
##
|
638
|
+
# Generate Java class(es)
|
639
|
+
# * *Args* :
|
640
|
+
# - +structs+ -> Dictionary of structs
|
641
|
+
# - +opts+ -> Dictionary that contains generation params [file, debug, package, parent_class, target_dir]
|
536
642
|
def generate_code(structs, opts)
|
537
643
|
$debug_java = true if opts[:debug]
|
538
644
|
base_template = Erubis::Eruby.new(java_base_class_template_str)
|
@@ -548,7 +654,7 @@ EOS
|
|
548
654
|
toplevel = opts[:parent_class] || nil
|
549
655
|
toplevel = " extends #{toplevel}" if toplevel
|
550
656
|
if opts[:package]
|
551
|
-
res = [{file: "
|
657
|
+
res = [{file: "Divine.java", src: "#{java_get_begin_module(opts)}public #{base_template.result({ toplevel_class: toplevel })}"}]
|
552
658
|
for cls in src
|
553
659
|
res << {file: cls.match(/class (.*) extends/)[1]+".java", src: "#{java_get_begin_module(opts)}public #{cls}"}
|
554
660
|
end
|
@@ -557,7 +663,11 @@ EOS
|
|
557
663
|
return [{file: opts[:file], src: "#{java_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel })}\n\n#{src.join("\n\n")}"}]
|
558
664
|
end
|
559
665
|
end
|
560
|
-
|
666
|
+
##
|
667
|
+
# Build package name and list of imports
|
668
|
+
# * *Args* :
|
669
|
+
# - +opts+ -> Dictionary that contains package name in key 'package'
|
670
|
+
#
|
561
671
|
def java_get_begin_module(opts)
|
562
672
|
str = "#{get_header_comment}\n\n"
|
563
673
|
str << "package #{opts[:package]};" if opts[:package]
|
@@ -565,7 +675,9 @@ EOS
|
|
565
675
|
str << "\n\n"
|
566
676
|
return str
|
567
677
|
end
|
568
|
-
|
678
|
+
##
|
679
|
+
# Generate list of imports needed in generated java classes
|
680
|
+
#
|
569
681
|
def get_java_imports
|
570
682
|
[
|
571
683
|
"java.io.ByteArrayInputStream",
|
@@ -6,14 +6,27 @@
|
|
6
6
|
|
7
7
|
module Divine
|
8
8
|
$debug_javascript = false
|
9
|
-
|
9
|
+
##
|
10
|
+
# * +JS Helper+ :
|
11
|
+
# Support base function needed to build base divine functions and DSL structs
|
12
|
+
#
|
10
13
|
class JavascriptHelperMethods < BabelHelperMethods
|
14
|
+
|
15
|
+
#
|
16
|
+
# Return the header comment
|
17
|
+
#
|
11
18
|
def get_header_comment
|
12
19
|
get_header_comment_text.map do |s|
|
13
20
|
"// #{s}"
|
14
21
|
end.join("\n")
|
15
22
|
end
|
16
|
-
|
23
|
+
##
|
24
|
+
# Generate the base functions of:
|
25
|
+
# * serialize
|
26
|
+
# * deserialize
|
27
|
+
# * Read Methods
|
28
|
+
# * Write Methods
|
29
|
+
|
17
30
|
def javascript_base_class_template_str
|
18
31
|
<<EOS
|
19
32
|
// ------------------------------------------------------------ DivineDataReader
|
@@ -114,6 +127,29 @@ DivineHelper.prototype.read_sint64 = function (data) {
|
|
114
127
|
}
|
115
128
|
}
|
116
129
|
|
130
|
+
DivineHelper.prototype.read_dint63 = function (data) {
|
131
|
+
var byte = this.read_int8(data)
|
132
|
+
var part1 = part2 = ""; // To hold first 32-bit and second 32-bit respectively
|
133
|
+
var bin = byte & 0x7F; // tmp To hold binary string
|
134
|
+
var numBytes = 1;
|
135
|
+
while ((byte >> 7) == 1) {
|
136
|
+
byte = this.read_int8(data)
|
137
|
+
bin = bin << 7
|
138
|
+
bin = bin | byte & 0x7F
|
139
|
+
numBytes ++;
|
140
|
+
if (numBytes == 4 && (byte >> 7) == 1){
|
141
|
+
part1 = bin.toString(2);
|
142
|
+
bin = 1; // To avoid unshifting of zero
|
143
|
+
}
|
144
|
+
}
|
145
|
+
bin = bin.toString(2);
|
146
|
+
if (bin.length > 1 && part1 != "")
|
147
|
+
bin = bin.substr(1, bin.length);
|
148
|
+
part2 = bin;
|
149
|
+
var val = parseInt(part1 + part2, 2);
|
150
|
+
return val;
|
151
|
+
}
|
152
|
+
|
117
153
|
DivineHelper.prototype.read_binary = function (data) {
|
118
154
|
return data.read(this.read_int32(data));
|
119
155
|
};
|
@@ -230,6 +266,23 @@ DivineHelper.prototype.write_sint64 = function (v, out) {
|
|
230
266
|
this.write_int32(parseInt(part2, 2), out);
|
231
267
|
}
|
232
268
|
|
269
|
+
DivineHelper.prototype.write_dint63 = function (v, out) {
|
270
|
+
var max = Math.pow(2, 53) - 1;
|
271
|
+
var min = 0;
|
272
|
+
if (v > max) // Max 9,007,199,254,740,991
|
273
|
+
this.raise_error("Too large Dynamic Int53 number: " + v + ", Max = " + max);
|
274
|
+
if (v < min) // Min 0
|
275
|
+
this.raise_error("Too small Dynamic Int53 number: " + v + ", Min = " + min);
|
276
|
+
|
277
|
+
bytes = v.toString(2).split("").reverse().join("").split(/(.{7})/).filter(function(t){if (t != "" ) return true});
|
278
|
+
for (var i = bytes.length - 1; i >= 0; i--){
|
279
|
+
var bin = bytes[i];
|
280
|
+
bin += Array(8 - bin.length).join("0") + Math.min(i,1);
|
281
|
+
var val = parseInt(bin.split("").reverse().join(""), 2);
|
282
|
+
this.write_int8(val, out);
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
233
286
|
DivineHelper.prototype.write_bool = function (v, out) {
|
234
287
|
this.write_int8(v ? 1 : 0, out)
|
235
288
|
}
|
@@ -454,6 +507,11 @@ DivineHelper.prototype.raise_error = function (msg) {
|
|
454
507
|
EOS
|
455
508
|
end
|
456
509
|
|
510
|
+
##
|
511
|
+
# Generate required functions that corresponding to the struct definition
|
512
|
+
# * *Args* :
|
513
|
+
# - +sh+ -> Struct Name
|
514
|
+
|
457
515
|
def javascript_class_template(sh)
|
458
516
|
code = [
|
459
517
|
"",
|
@@ -537,6 +595,29 @@ EOS
|
|
537
595
|
format_src(0, 3, code)
|
538
596
|
end
|
539
597
|
|
598
|
+
##
|
599
|
+
# Generate default JS data types declaration values corresponding to each DSL types:
|
600
|
+
# * DSL Type --> Corresponding Default JS Value
|
601
|
+
# * dint63 --> 0 range -> [0 - 9.007.199.254.740.991]
|
602
|
+
# * 1 byte: range -> [0 - 127]
|
603
|
+
# * 2 bytes: range -> [0 - 16,383]
|
604
|
+
# * 3 bytes: range -> [0 - 2,097,151]
|
605
|
+
# * 4 bytes: range -> [0 - 268,435,455]
|
606
|
+
# * 5 bytes: range -> [0 - 34,359,738,367]
|
607
|
+
# * 6 bytes: range -> [0 - 4,398,046,511,103]
|
608
|
+
# * 7 bytes: range -> [0 - 562,949,953,421,311]
|
609
|
+
# * 8 bytes: range -> [0 - 9.007.199.254.740.991] (limited by 53-bit)
|
610
|
+
# * int8 --> 0 Range -> [0 - 255]
|
611
|
+
# * int16 --> 0 Range -> [0 - 65535]
|
612
|
+
# * int32 --> 0 Range -> [0 - 4.294.967.295]
|
613
|
+
# * sint32 --> 0 Range -> [-2.147.483.648 - 2.147.483.647]
|
614
|
+
# * sint64 --> 0 Range -> [-9.007.199.254.740.992, 9.007.199.254.740.991] (limited by 53-bit)
|
615
|
+
# * string --> ""
|
616
|
+
# * ip_number--> ""
|
617
|
+
# * binary --> []
|
618
|
+
# * short_binary --> []
|
619
|
+
# * list --> []
|
620
|
+
# * map --> {}
|
540
621
|
|
541
622
|
def javascript_get_empty_declaration(field)
|
542
623
|
case field.type
|
@@ -544,7 +625,7 @@ EOS
|
|
544
625
|
"[]"
|
545
626
|
when :map
|
546
627
|
"{}"
|
547
|
-
when :int8, :int16, :int32, :sint32, :sint64
|
628
|
+
when :int8, :int16, :int32, :sint32, :sint64, :dint63
|
548
629
|
"0"
|
549
630
|
when :string, :ip_number
|
550
631
|
"\"\""
|
@@ -553,6 +634,12 @@ EOS
|
|
553
634
|
end
|
554
635
|
end
|
555
636
|
|
637
|
+
##
|
638
|
+
# Generate the way of serializing different DSL types
|
639
|
+
# * *Args* :
|
640
|
+
# - +var+ -> variable name
|
641
|
+
# - +types+ -> variable type
|
642
|
+
|
556
643
|
def javascript_serialize_internal(var, types)
|
557
644
|
if types.respond_to? :first
|
558
645
|
case types.first
|
@@ -600,6 +687,12 @@ EOS
|
|
600
687
|
end
|
601
688
|
end
|
602
689
|
|
690
|
+
##
|
691
|
+
# Generate the way of deserializing different DSL types
|
692
|
+
# * *Args* :
|
693
|
+
# - +var+ -> variable name
|
694
|
+
# - +types+ -> variable type
|
695
|
+
|
603
696
|
def javascript_deserialize_internal(var, types)
|
604
697
|
if types.respond_to? :first
|
605
698
|
case types.first
|
@@ -656,8 +749,18 @@ EOS
|
|
656
749
|
end
|
657
750
|
|
658
751
|
|
752
|
+
##
|
753
|
+
# Responsible for generating Divine and structs functions
|
754
|
+
#
|
659
755
|
|
660
756
|
class JavascriptGenerator < JavascriptHelperMethods
|
757
|
+
|
758
|
+
##
|
759
|
+
# Generate JS Functions
|
760
|
+
# * *Args* :
|
761
|
+
# - +structs+ -> Dictionary of structs
|
762
|
+
# - +opts+ -> Dictionary that contains generation params [file, debug, parent_class, target_dir]
|
763
|
+
|
661
764
|
def generate_code(structs, opts)
|
662
765
|
$debug_javascript = true if opts[:debug]
|
663
766
|
base_template = Erubis::Eruby.new(javascript_base_class_template_str)
|
@@ -674,11 +777,15 @@ EOS
|
|
674
777
|
toplevel = " < #{toplevel}" if toplevel
|
675
778
|
return [{file: opts[:file], src: "#{javascript_get_begin_module(opts)}#{base_template.result({ toplevel_class: toplevel })}\n\n#{src.join("\n\n")}#{javascript_get_end_module(opts)}"}]
|
676
779
|
end
|
677
|
-
|
780
|
+
|
781
|
+
#
|
782
|
+
# Build Header Comments
|
783
|
+
#
|
678
784
|
def javascript_get_begin_module(opts)
|
679
785
|
"#{get_header_comment}\n\n"
|
680
786
|
end
|
681
787
|
|
788
|
+
# Do nothing
|
682
789
|
def javascript_get_end_module(opts)
|
683
790
|
nil
|
684
791
|
end
|
@@ -1,15 +1,32 @@
|
|
1
1
|
module Divine
|
2
2
|
|
3
|
+
##
|
4
|
+
# * +Ruby Helper+ :
|
5
|
+
# Support base function needed to build Divine enviroment and classes corresponding to DSL structs
|
6
|
+
#
|
3
7
|
class RubyHelperMethods < BabelHelperMethods
|
8
|
+
|
9
|
+
#
|
10
|
+
# Return the header comment
|
11
|
+
#
|
4
12
|
def get_header_comment
|
5
13
|
get_header_comment_text.map do |s|
|
6
14
|
"# #{s}"
|
7
15
|
end.join("\n")
|
8
16
|
end
|
9
17
|
|
18
|
+
##
|
19
|
+
# Generate the base Divine Ruby Class
|
20
|
+
# that contains the main methods:
|
21
|
+
# * serialize
|
22
|
+
# * serialize Internal
|
23
|
+
# * deserialize
|
24
|
+
# * Read Methods
|
25
|
+
# * Write Methods
|
26
|
+
|
10
27
|
def ruby_base_class_template_str
|
11
28
|
%q{
|
12
|
-
class
|
29
|
+
class Divine<%= toplevel_class %>
|
13
30
|
public
|
14
31
|
def serialize
|
15
32
|
out = []
|
@@ -53,6 +70,17 @@ module Divine
|
|
53
70
|
return num
|
54
71
|
end
|
55
72
|
|
73
|
+
def read_dint63(data)
|
74
|
+
byte = read_int8(data)
|
75
|
+
val = byte & 0x7F
|
76
|
+
while (byte >> 7) == 1
|
77
|
+
byte = read_int8(data)
|
78
|
+
val = val << 7
|
79
|
+
val = val | byte & 0x7F
|
80
|
+
end
|
81
|
+
val
|
82
|
+
end
|
83
|
+
|
56
84
|
def read_bool(data)
|
57
85
|
read_int8(data) == 1
|
58
86
|
end
|
@@ -145,12 +173,26 @@ module Divine
|
|
145
173
|
v = v.to_i
|
146
174
|
max = (2** (64 - 1)) - 1
|
147
175
|
min = (2** (64 - 1) ) - (2** 64)
|
148
|
-
raise_error "Too large
|
149
|
-
raise_error "Too small
|
176
|
+
raise_error "Too large Sint64 number: #{v} , Max = #{max}" if v > max # Max 9.223.372.036.854.775.807
|
177
|
+
raise_error "Too small sInt64 number: #{v} , Min = #{min}" if v < min # Min -9.223.372.036.854.775.808
|
150
178
|
write_int32( v >> 32 & 0xFFFFFFFF, out)
|
151
179
|
write_int32( v & 0xFFFFFFFF, out)
|
152
180
|
end
|
153
181
|
|
182
|
+
def write_dint63(v, out)
|
183
|
+
v = v.to_i
|
184
|
+
max = (2** (64 - 1)) - 1
|
185
|
+
min = 0
|
186
|
+
raise_error "Too large Dynamic int63 number: #{v} , Max = #{max}" if v > max # Max 9.223.372.036.854.775.807
|
187
|
+
raise_error "Too small Dynamic int63 number: #{v} , Min = #{min}" if v < min # Min 0
|
188
|
+
|
189
|
+
bytes = v.to_s(2).reverse.split(/([01]{7})/).reject{ |t| t == ""}.each_with_index.map{ |t, i| t = t + "0"*(7-t.length) + [i,1].min.to_s}
|
190
|
+
bytes.reverse.map{ |t|
|
191
|
+
val = t.reverse.to_i 2
|
192
|
+
write_int8(val, out)
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
154
196
|
def write_bool(v, out)
|
155
197
|
write_int8(v ? 1 : 0, out)
|
156
198
|
end
|
@@ -279,10 +321,14 @@ module Divine
|
|
279
321
|
end
|
280
322
|
}
|
281
323
|
end
|
324
|
+
##
|
325
|
+
# Generate Ruby Class that corresponding to the struct definition
|
326
|
+
# * *Args* :
|
327
|
+
# - +sh+ -> Struct Name
|
282
328
|
|
283
329
|
def ruby_class_template(sh)
|
284
330
|
code = [
|
285
|
-
"class #{sh.name} <
|
331
|
+
"class #{sh.name} < Divine",
|
286
332
|
:indent,
|
287
333
|
"",
|
288
334
|
|
@@ -364,7 +410,30 @@ module Divine
|
|
364
410
|
]
|
365
411
|
format_src(0, 3, code)
|
366
412
|
end
|
367
|
-
|
413
|
+
##
|
414
|
+
# Generate default Ruby data types declaration values corresponding to each DSL types:
|
415
|
+
# * DSL Type --> Corresponding Default Ruby Value
|
416
|
+
# * dint63 --> 0 range -> [0 - 9,223,372,036,854,775,807]
|
417
|
+
# * 1 byte: range -> [0 - 127]
|
418
|
+
# * 2 bytes: range -> [0 - 16,383]
|
419
|
+
# * 3 bytes: range -> [0 - 2,097,151]
|
420
|
+
# * 4 bytes: range -> [0 - 268,435,455]
|
421
|
+
# * 5 bytes: range -> [0 - 34,359,738,367]
|
422
|
+
# * 6 bytes: range -> [0 - 4,398,046,511,103]
|
423
|
+
# * 7 bytes: range -> [0 - 562,949,953,421,311]
|
424
|
+
# * 8 bytes: range -> [0 - 72,057,594,037,927,935]
|
425
|
+
# * 9 bytes: range -> [0 - 9,223,372,036,854,775,807]
|
426
|
+
# * int8 --> 0 Range -> [0 - 255]
|
427
|
+
# * int16 --> 0 Range -> [0 - 65535]
|
428
|
+
# * int32 --> 0 Range -> [0 - 4.294.967.295]
|
429
|
+
# * sint32 --> 0 Range -> [-2.147.483.648 - 2.147.483.647]
|
430
|
+
# * sint64 --> 0 Range -> [-9.223.372.036.854.775.808, 9.223.372.036.854.775.807]
|
431
|
+
# * string --> ""
|
432
|
+
# * ip_number--> ""
|
433
|
+
# * binary --> []
|
434
|
+
# * short_binary --> []
|
435
|
+
# * list --> []
|
436
|
+
# * map --> {}
|
368
437
|
|
369
438
|
def ruby_get_empty_declaration(field)
|
370
439
|
case field.type
|
@@ -372,7 +441,7 @@ module Divine
|
|
372
441
|
"[]"
|
373
442
|
when :map
|
374
443
|
"{}"
|
375
|
-
when :int8, :int16, :int32, :sint32, :sint64
|
444
|
+
when :dint63, :int8, :int16, :int32, :sint32, :sint64
|
376
445
|
"0"
|
377
446
|
when :string, :ip_number
|
378
447
|
"\"\""
|
@@ -381,6 +450,12 @@ module Divine
|
|
381
450
|
end
|
382
451
|
end
|
383
452
|
|
453
|
+
##
|
454
|
+
# Generate the way of serializing different DSL types
|
455
|
+
# * *Args* :
|
456
|
+
# - +var+ -> variable name
|
457
|
+
# - +types+ -> variable type
|
458
|
+
|
384
459
|
def ruby_serialize_internal(var, types)
|
385
460
|
if types.respond_to? :first
|
386
461
|
case types.first
|
@@ -422,6 +497,12 @@ module Divine
|
|
422
497
|
end
|
423
498
|
end
|
424
499
|
|
500
|
+
##
|
501
|
+
# Generate the way of deserializing different DSL types
|
502
|
+
# * *Args* :
|
503
|
+
# - +var+ -> variable name
|
504
|
+
# - +types+ -> variable type
|
505
|
+
|
425
506
|
def ruby_deserialize_internal(var, types)
|
426
507
|
if types.respond_to? :first
|
427
508
|
case types.first
|
@@ -476,10 +557,17 @@ module Divine
|
|
476
557
|
end
|
477
558
|
|
478
559
|
|
479
|
-
|
560
|
+
##
|
561
|
+
# Responsible for generating Divine and structs classes
|
562
|
+
#
|
480
563
|
class RubyGenerator < RubyHelperMethods
|
481
564
|
@debug = true
|
482
|
-
|
565
|
+
##
|
566
|
+
# Generate Ruby class(es)
|
567
|
+
# * *Args* :
|
568
|
+
# - +structs+ -> Dictionary of structs
|
569
|
+
# - +opts+ -> Dictionary that contains generation params [file, module, parent_class, target_dir]
|
570
|
+
|
483
571
|
def generate_code(structs, opts)
|
484
572
|
base_template = Erubis::Eruby.new(ruby_base_class_template_str)
|
485
573
|
keys = structs.keys.sort
|
@@ -496,6 +584,11 @@ module Divine
|
|
496
584
|
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)}"}]
|
497
585
|
end
|
498
586
|
|
587
|
+
##
|
588
|
+
# Build module name
|
589
|
+
# * *Args* :
|
590
|
+
# - +opts+ -> Dictionary contains module name in key module
|
591
|
+
|
499
592
|
def ruby_get_begin_module(opts)
|
500
593
|
if opts[:module]
|
501
594
|
"module #{opts[:module]}\n\n"
|
@@ -503,7 +596,8 @@ module Divine
|
|
503
596
|
nil
|
504
597
|
end
|
505
598
|
end
|
506
|
-
|
599
|
+
##
|
600
|
+
# Ending the module
|
507
601
|
def ruby_get_end_module(opts)
|
508
602
|
if opts[:module]
|
509
603
|
"\n\nend\n"
|