autoc 1.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +3 -0
  3. data/README.md +149 -0
  4. data/cmake/AutoC.cmake +39 -0
  5. data/lib/autoc/allocators.rb +51 -0
  6. data/lib/autoc/association.rb +126 -0
  7. data/lib/autoc/box.rb +311 -0
  8. data/lib/autoc/cmake.rb +54 -0
  9. data/lib/autoc/collection.rb +83 -110
  10. data/lib/autoc/composite.rb +333 -0
  11. data/lib/autoc/cstring.rb +263 -0
  12. data/lib/autoc/function.rb +247 -0
  13. data/lib/autoc/hash_map.rb +328 -0
  14. data/lib/autoc/hash_set.rb +339 -0
  15. data/lib/autoc/hashers.rb +102 -0
  16. data/lib/autoc/list.rb +444 -0
  17. data/lib/autoc/module.rb +434 -0
  18. data/lib/autoc/openmp.rb +15 -0
  19. data/lib/autoc/primitive.rb +27 -0
  20. data/lib/autoc/ranges.rb +707 -0
  21. data/lib/autoc/record.rb +247 -0
  22. data/lib/autoc/scaffold/docs.rb +117 -0
  23. data/lib/autoc/scaffold/generic_value.rb +86 -0
  24. data/lib/autoc/scaffold/project.rb +75 -0
  25. data/lib/autoc/scaffold/test_cstring.rb +113 -0
  26. data/lib/autoc/scaffold/test_cstring_hash_set.rb +35 -0
  27. data/lib/autoc/scaffold/test_int_box.rb +22 -0
  28. data/lib/autoc/scaffold/test_int_hash_set.rb +448 -0
  29. data/lib/autoc/scaffold/test_int_list.rb +106 -0
  30. data/lib/autoc/scaffold/test_int_vector.rb +83 -0
  31. data/lib/autoc/scaffold/test_v2v_hash_map.rb +83 -0
  32. data/lib/autoc/scaffold/test_value_hash_set.rb +60 -0
  33. data/lib/autoc/scaffold/test_value_vector.rb +146 -0
  34. data/{test/test.rb → lib/autoc/scaffold/tests.rb} +179 -158
  35. data/lib/autoc/scaffold.rb +12 -0
  36. data/lib/autoc/sequential.rb +99 -0
  37. data/lib/autoc/set.rb +331 -0
  38. data/lib/autoc/std.rb +149 -0
  39. data/lib/autoc/type.rb +93 -531
  40. data/lib/autoc/vector.rb +290 -0
  41. data/lib/autoc.rb +4 -35
  42. metadata +55 -85
  43. data/.yardopts +0 -4
  44. data/CHANGES +0 -23
  45. data/README +0 -28
  46. data/doc/AutoC/Code.html +0 -523
  47. data/doc/AutoC/Collection.html +0 -1214
  48. data/doc/AutoC/HashMap.html +0 -1441
  49. data/doc/AutoC/HashSet.html +0 -916
  50. data/doc/AutoC/Iterators/Bidirectional.html +0 -204
  51. data/doc/AutoC/Iterators/Unidirectional.html +0 -200
  52. data/doc/AutoC/Iterators.html +0 -126
  53. data/doc/AutoC/List.html +0 -1039
  54. data/doc/AutoC/Maps.html +0 -290
  55. data/doc/AutoC/Module/File.html +0 -415
  56. data/doc/AutoC/Module/Header.html +0 -437
  57. data/doc/AutoC/Module/Source.html +0 -707
  58. data/doc/AutoC/Module.html +0 -948
  59. data/doc/AutoC/Priority.html +0 -138
  60. data/doc/AutoC/Queue.html +0 -1172
  61. data/doc/AutoC/Reference.html +0 -735
  62. data/doc/AutoC/Sets.html +0 -520
  63. data/doc/AutoC/String.html +0 -1394
  64. data/doc/AutoC/TreeMap.html +0 -1565
  65. data/doc/AutoC/TreeSet.html +0 -1447
  66. data/doc/AutoC/Type.html +0 -2148
  67. data/doc/AutoC/UserDefinedType.html +0 -1047
  68. data/doc/AutoC/Vector.html +0 -987
  69. data/doc/AutoC.html +0 -331
  70. data/doc/_index.html +0 -388
  71. data/doc/class_list.html +0 -51
  72. data/doc/css/common.css +0 -1
  73. data/doc/css/full_list.css +0 -58
  74. data/doc/css/style.css +0 -481
  75. data/doc/file.CHANGES.html +0 -117
  76. data/doc/file.README.html +0 -116
  77. data/doc/file_list.html +0 -61
  78. data/doc/frames.html +0 -17
  79. data/doc/index.html +0 -116
  80. data/doc/js/app.js +0 -243
  81. data/doc/js/full_list.js +0 -216
  82. data/doc/js/jquery.js +0 -4
  83. data/doc/method_list.html +0 -1307
  84. data/doc/top-level-namespace.html +0 -112
  85. data/lib/autoc/code.rb +0 -237
  86. data/lib/autoc/collection/hash_map.rb +0 -385
  87. data/lib/autoc/collection/hash_set.rb +0 -337
  88. data/lib/autoc/collection/iterator.rb +0 -39
  89. data/lib/autoc/collection/list.rb +0 -429
  90. data/lib/autoc/collection/map.rb +0 -41
  91. data/lib/autoc/collection/queue.rb +0 -517
  92. data/lib/autoc/collection/set.rb +0 -134
  93. data/lib/autoc/collection/tree_map.rb +0 -464
  94. data/lib/autoc/collection/tree_set.rb +0 -611
  95. data/lib/autoc/collection/vector.rb +0 -336
  96. data/lib/autoc/string.rb +0 -492
  97. data/test/test_auto.c +0 -7141
  98. data/test/test_auto.h +0 -753
  99. data/test/test_char_string.rb +0 -270
  100. data/test/test_int_list.rb +0 -35
  101. data/test/test_int_tree_set.rb +0 -111
  102. data/test/test_int_vector.rb +0 -34
  103. data/test/test_value_hash_map.rb +0 -162
  104. data/test/test_value_hash_set.rb +0 -173
  105. data/test/test_value_list.rb +0 -193
  106. data/test/test_value_queue.rb +0 -275
  107. data/test/test_value_tree_map.rb +0 -176
  108. data/test/test_value_tree_set.rb +0 -173
  109. data/test/test_value_vector.rb +0 -155
  110. data/test/value.rb +0 -80
@@ -0,0 +1,434 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'set'
5
+ require 'digest'
6
+
7
+ require 'autoc'
8
+
9
+
10
+ module AutoC
11
+
12
+
13
+ class Module
14
+
15
+ # @private
16
+ module EntityContainer
17
+
18
+ def entities = @entities ||= ::Set.new
19
+
20
+ def <<(entity)
21
+ entities << entity
22
+ self
23
+ end
24
+
25
+ end # EntityContainer
26
+
27
+ # @private
28
+ class Builder < ::Array
29
+
30
+ attr_reader :complexity
31
+
32
+ def initialize
33
+ @complexity = 0
34
+ super
35
+ end
36
+
37
+ def <<(obj)
38
+ @complexity += (s = obj.to_s).size
39
+ super(s)
40
+ end
41
+
42
+ end
43
+
44
+ include EntityContainer
45
+
46
+ CAP = "/* Automagically generated by AutoC #{AutoC::VERSION} */"
47
+
48
+ attr_reader :name
49
+
50
+ attr_accessor :source_count
51
+
52
+ attr_accessor :source_threshold
53
+
54
+ def initialize(name) = @name = name
55
+
56
+ def header = @header ||= Header.new(self)
57
+
58
+ def sources = @sources ||= (1..source_count).collect { |i| Source.new(self, i) }
59
+
60
+ def digests = @digests ||= State.new(self).read
61
+
62
+ def render
63
+ distribute_entities
64
+ header.render
65
+ sources.each(&:render)
66
+ State.new(self).collect.write
67
+ self
68
+ end
69
+
70
+ def total_entities
71
+ @total_entities ||= begin
72
+ set = ::Set.new
73
+ entities.each { |e| set.merge(e.total_references) }
74
+ set
75
+ end
76
+ end
77
+
78
+ private def distribute_entities
79
+ header.entities.merge(total_entities)
80
+ if source_count.nil?
81
+ @source_count = source_threshold.nil? ? 1 : (total_entities.sum(&:complexity).to_f / source_threshold).ceil
82
+ end
83
+ total_entities.each do |e|
84
+ sources.sort! { |lt, rt| lt.complexity <=> rt.complexity }
85
+ sources.first << e
86
+ end
87
+ end
88
+
89
+ def self.render(name, &code)
90
+ m = self.new(name)
91
+ yield(m) if block_given?
92
+ m.render
93
+ end
94
+
95
+ end # Module
96
+
97
+
98
+ # @private
99
+ class Module::State < ::Hash
100
+
101
+ attr_reader :module
102
+
103
+ def file_name = "#{self.module.name}.state"
104
+
105
+ def initialize(m)
106
+ super
107
+ @module = m
108
+ end
109
+
110
+ def collect
111
+ self[self.module.header.file_name] = self.module.header.digest
112
+ self.module.sources.each { |source| self[source.file_name] = source.digest }
113
+ self
114
+ end
115
+
116
+ def read
117
+ if File.exist?(file_name)
118
+ # It's OK not to have this file but if it exists it must have proper contents
119
+ io = File.open(file_name, 'rt', chomp: true)
120
+ begin
121
+ hash = {}
122
+ io.readlines.each do |x|
123
+ raise 'improper state file format' if (/\s*([^\s]+)\s+\*(.*)/ =~ x).nil?
124
+ hash[$2] = $1
125
+ end
126
+ update(hash)
127
+ ensure
128
+ io.close
129
+ end
130
+ end
131
+ self
132
+ end
133
+
134
+ def write
135
+ io = File.open(file_name, 'wt')
136
+ begin
137
+ begin
138
+ each { |file_name, digest| io << "#{digest} *#{file_name}\n" }
139
+ ensure
140
+ io.close
141
+ end
142
+ rescue
143
+ File.unlink(file_name) # Delete improperly rendered state file
144
+ raise
145
+ end
146
+ self
147
+ end
148
+
149
+ end # State
150
+
151
+
152
+ # @private
153
+ class Module::StreamFile < File
154
+
155
+ def digest = @digest.hexdigest
156
+
157
+ def initialize(*args, **kws)
158
+ super(*args, **kws)
159
+ @digest = Digest::MD5.new
160
+ end
161
+
162
+ def <<(data)
163
+ super(data)
164
+ @digest.update(data)
165
+ self
166
+ end
167
+
168
+ end # StreamFile
169
+
170
+
171
+ # @private
172
+ module Module::SmartRenderer
173
+
174
+ # def render_contents(stream)
175
+
176
+ attr_reader :digest
177
+
178
+ def render
179
+ io = stream
180
+ _file_name = io.path # Memorize temporary file name
181
+ begin
182
+ begin
183
+ render_contents(io)
184
+ @digest = io.digest
185
+ ensure
186
+ io.close
187
+ end
188
+ rescue
189
+ File.unlink(_file_name) # Remove improperly rendered temporary file
190
+ raise
191
+ else
192
+ if !File.exist?(file_name) || self.module.digests[file_name] != digest
193
+ File.rename(_file_name, file_name) # Rendered temporary has different digest - replace original permanent file with it
194
+ else
195
+ File.unlink(_file_name) # New temporary has the same digest as permanent - no need to replace the latter, delete the temporary instead
196
+ end
197
+ end
198
+ end
199
+
200
+ end # SmartRenderer
201
+
202
+
203
+ class Module::Header
204
+
205
+ include Module::EntityContainer
206
+
207
+ include Module::SmartRenderer
208
+
209
+ attr_reader :module
210
+
211
+ def file_name = @file_name ||= "#{self.module.name}_auto.h"
212
+
213
+ def tag = "#{self.module.name}_auto_h".upcase
214
+
215
+ def initialize(m) = @module = m
216
+
217
+ private
218
+
219
+ def render_contents(stream)
220
+ render_prologue(stream)
221
+ entities.to_a.sort.each { |e| e.interface.each { |x| stream << x } }
222
+ render_epilogue(stream)
223
+ end
224
+
225
+ def render_prologue(stream)
226
+ stream << %{
227
+ #{Module::CAP}
228
+ #ifndef #{tag}
229
+ #define #{tag}
230
+ }
231
+ end
232
+
233
+ def render_epilogue(stream)
234
+ stream << %{
235
+ #endif
236
+ }
237
+ end
238
+
239
+ def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')
240
+
241
+ end # Header
242
+
243
+
244
+ class Module::Source
245
+
246
+ include Module::EntityContainer
247
+
248
+ include Module::SmartRenderer
249
+
250
+ attr_reader :module
251
+
252
+ attr_reader :complexity
253
+
254
+ attr_reader :index
255
+
256
+ def file_name = self.module.source_count < 2 ? "#{self.module.name}_auto.c" : "#{self.module.name}_auto#{index}.c"
257
+
258
+ def initialize(m, index)
259
+ @module = m
260
+ @complexity = 0
261
+ @index = index
262
+ end
263
+
264
+ def <<(entity)
265
+ @complexity += entity.complexity unless entities.include?(entity)
266
+ super
267
+ end
268
+
269
+ private
270
+
271
+ def render_contents(stream)
272
+ render_prologue(stream)
273
+ total_entities = ::Set.new
274
+ entities.each { |e| total_entities.merge(e.total_references) }
275
+ total_entities.to_a.sort.each { |e| e.forward_declarations.each { |x| stream << x } }
276
+ entities.to_a.sort.each { |e| e.implementation.each { |x| stream << x } }
277
+ end
278
+
279
+ def render_prologue(stream)
280
+ stream << %{
281
+ #{Module::CAP}
282
+ #include "#{self.module.header.file_name}"
283
+ }
284
+ end
285
+
286
+ def stream = @stream ||= Module::StreamFile.new(file_name+'~', 'wt')
287
+
288
+ end # Source
289
+
290
+
291
+ module Entity
292
+
293
+ include ::Comparable
294
+
295
+ # A set of the entity's immediate references which, unlike dependencies, do not enforce the entities relative ordering
296
+ def references = @references ||= ReferenceSet.new
297
+
298
+ # Return the entire entity's reference set staring with self
299
+ def total_references = @total_references ||= collect_references(::Set.new)
300
+
301
+ # A set of the entity's immediate dependencies which enforce the entities relative ordering
302
+ def dependencies = @dependencies ||= DependencySet.new(self)
303
+
304
+ # Return the entire entity's dependency set staring with self
305
+ def total_dependencies = @total_dependencies ||= collect_dependencies(::Set.new)
306
+
307
+ protected def collect_references(set)
308
+ unless set.include?(self)
309
+ set << self
310
+ references.each { |x| x.collect_references(set) }
311
+ end
312
+ set
313
+ end
314
+
315
+ protected def collect_dependencies(set)
316
+ unless set.include?(self)
317
+ set << self
318
+ dependencies.each { |x| x.collect_dependencies(set) }
319
+ end
320
+ set
321
+ end
322
+
323
+ def <=>(other) = position <=> other.position
324
+
325
+ # Compute the entity's relative position with respect to its dependencies
326
+ def position = @position ||= begin
327
+ p = 0
328
+ # This code goes into infinite recursion on circular dependency
329
+ # which must be resolved manually with Entity#references
330
+ total_dependencies.each do |d|
331
+ unless equal?(d)
332
+ dp = d.position
333
+ p = dp if p < dp # p <- max(p, dp)
334
+ end
335
+ end
336
+ p + 1 # Arrange entity to follow all its dependencies
337
+ end
338
+
339
+ def complexity = forward_declarations.complexity + implementation.complexity # Interface part is not considered as it is shared across the sources
340
+
341
+ def interface
342
+ @interface ||= begin
343
+ render_interface(stream = Module::Builder.new)
344
+ stream
345
+ end
346
+ end
347
+
348
+ def forward_declarations
349
+ @forward_declarations ||= begin
350
+ render_forward_declarations(stream = Module::Builder.new)
351
+ stream
352
+ end
353
+ end
354
+
355
+ def implementation
356
+ @implementation ||= begin
357
+ render_implementation(stream = Module::Builder.new)
358
+ stream
359
+ end
360
+ end
361
+
362
+ private
363
+
364
+ ### Overridable rendering methods
365
+
366
+ def render_interface(stream) = nil
367
+
368
+ def render_forward_declarations(stream) = nil
369
+
370
+ def render_implementation(stream) = nil
371
+
372
+ end # Entity
373
+
374
+
375
+ Entity::ReferenceSet = ::Set
376
+
377
+
378
+ # @private
379
+ class Entity::DependencySet < ::Set
380
+
381
+ def initialize(entity)
382
+ super()
383
+ @entity = entity
384
+ end
385
+
386
+ def <<(x)
387
+ @entity.references << x # Each dependency is also registered as a reference
388
+ super
389
+ end
390
+
391
+ end # DependencySet
392
+
393
+
394
+ # Helper class to represent plain C side code block
395
+ class Code
396
+
397
+ include Entity
398
+
399
+ def initialize(interface: nil, implementation: nil, definitions: nil)
400
+ @interface_ = interface
401
+ @definitions_ = definitions
402
+ @implementation_ = implementation
403
+ end
404
+
405
+ def inspect = "... <#{self.class}>"
406
+
407
+ private
408
+
409
+ def render_interface(stream)
410
+ stream << @interface_ unless @interface_.nil?
411
+ end
412
+
413
+ def render_implementation(stream)
414
+ stream << @implementation_ unless @implementation_.nil?
415
+ end
416
+
417
+ def render_forward_declarations(stream)
418
+ stream << @definitions_ unless @definitions_.nil?
419
+ end
420
+
421
+ end # Code
422
+
423
+
424
+ # Helper class to inject a system-wide header into the C side interface part of the module
425
+ class SystemHeader < AutoC::Code
426
+ def initialize(header)
427
+ super interface: %{
428
+ #include <#{header}>
429
+ }
430
+ end
431
+ end # SystemHeader
432
+
433
+
434
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/module'
5
+
6
+
7
+ module AutoC
8
+
9
+ OMP_H = Code.new interface: %{
10
+ #ifdef _OPENMP
11
+ #include <omp.h>
12
+ #endif
13
+ }
14
+
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require 'autoc/type'
5
+
6
+
7
+ module AutoC
8
+
9
+
10
+ class Primitive < Type
11
+
12
+ def default_create = @default_create ||= -> (target) { copy.(target, 0) }
13
+
14
+ def custom_create = @custom_create ||= -> (target, source) { copy.(target, source) }
15
+
16
+ def copy = @copy ||= -> (target, source) { "#{target} = #{source}" }
17
+
18
+ def equal = @equal ||= -> (lt, rt) { "#{lt} == #{rt}" }
19
+
20
+ def compare = @compare ||= -> (lt, rt) { "(#{lt} == #{rt} ? 0 : (#{lt} > #{rt} ? +1 : -1))" }
21
+
22
+ def hash_code = @hash_code ||= -> (target) { "(size_t)(#{target})" }
23
+
24
+ end # Primitive
25
+
26
+
27
+ end