autoc 1.1 → 1.2

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.
@@ -6,7 +6,7 @@
6
6
  <title>
7
7
  Top Level Namespace
8
8
 
9
- &mdash; Documentation by YARD 0.8.7.4
9
+ &mdash; Documentation by YARD 0.8.7.6
10
10
 
11
11
  </title>
12
12
 
@@ -103,9 +103,9 @@
103
103
  </div>
104
104
 
105
105
  <div id="footer">
106
- Generated on Mon Jun 9 18:28:02 2014 by
106
+ Generated on Sat Nov 22 16:58:03 2014 by
107
107
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
- 0.8.7.4 (ruby-2.0.0).
108
+ 0.8.7.6 (ruby-2.1.5).
109
109
  </div>
110
110
 
111
111
  </body>
@@ -2,8 +2,8 @@
2
2
 
3
3
  *AutoC* is a host of Ruby modules related to automatic C source code generation.
4
4
 
5
- . {AutoC::Code} - generic C multi-source module generator.
6
- . {AutoC::Collection} - strongly-typed data structure generators similar
5
+ . {AutoC::Code} generic C multi-source module generator.
6
+ . {AutoC::Collection} strongly-typed data structure generators similar
7
7
  to the C++ STL container classes.
8
8
 
9
9
  == Versioning scheme
@@ -21,7 +21,7 @@ Should the major incompatible changes be made, the new release 2.0 will be intro
21
21
 
22
22
  =end
23
23
  module AutoC
24
- VERSION = "1.1"
24
+ VERSION = "1.2"
25
25
  end # AutoC
26
26
 
27
27
 
@@ -17,6 +17,15 @@ module AutoC
17
17
  # end
18
18
 
19
19
 
20
+ # Convert obj to string and return it.
21
+ # Throw NameError is resulting string is not a valid C identifier.
22
+ def self.c_id(obj)
23
+ obj = obj.to_s
24
+ #raise NameError.new("#{obj} is not a valid C identifier", obj) if (/^[_a-zA-Z]\w*$/ =~ obj).nil?
25
+ obj
26
+ end
27
+
28
+
20
29
  # TODO min/max Fixnums
21
30
  module Priority
22
31
  DEFAULT = 0
@@ -70,10 +79,7 @@ class Module
70
79
  end
71
80
 
72
81
  def <<(obj)
73
- unless @entities.include?(obj)
74
- @entities << obj
75
- obj.entities.each {|e| self << e}
76
- end
82
+ obj.entities.each {|e| self << e} unless @entities.add?(obj).nil?
77
83
  self
78
84
  end
79
85
 
@@ -95,7 +101,7 @@ class Module
95
101
  (1..source_count).each {|i| @sources << new_source(i)}
96
102
  @main_source = @sources.first
97
103
  @smallest_source = @main_source
98
- # It appears that computing the size of a source might be a fairly expensive operation so do it only when neccessary
104
+ # It appears that computing the size of a source might be a fairly expensive operation so do it only when necessary
99
105
  refresh_smallest_source = source_count > 1
100
106
  @entities.each do |e|
101
107
  @header << e
@@ -7,17 +7,23 @@ module AutoC
7
7
 
8
8
  =begin
9
9
 
10
+ == Implemented types
11
+
12
+ - {AutoC::UserDefinedType} user-defined custom type
13
+
14
+ - {AutoC::Reference} counted reference type
15
+
10
16
  == Implemented collections
11
17
 
12
- - {AutoC::Vector} a fixed-sized array
18
+ - {AutoC::Vector} resizable array
13
19
 
14
- - {AutoC::List} a single linked list
20
+ - {AutoC::List} single linked list
15
21
 
16
- - {AutoC::Queue} a double linked list
22
+ - {AutoC::Queue} double linked list
17
23
 
18
- - {AutoC::HashSet} a hash-based set
24
+ - {AutoC::HashSet} hash-based set
19
25
 
20
- - {AutoC::HashMap} a hash-based map
26
+ - {AutoC::HashMap} hash-based map
21
27
 
22
28
  == Ruby side operation
23
29
 
@@ -29,13 +35,15 @@ AutoC::Module.generate!(:Test) do |c|
29
35
  c << AutoC::List.new(:IntList, :int)
30
36
  end
31
37
  ----
32
- In the above example a C module Test represented by the C header +test_auto.h+ and the C source +test_auto.c+ are generated.
38
+ In the above example a C module Test represented by the C header +test_auto.h+ and the C source +test_auto.c+ is generated.
33
39
  The C++ counterpart of the generated collection is +std::forward_list<int>+.
34
40
 
35
41
  == C interface
36
42
 
37
43
  === Element types: values, references
38
44
 
45
+ Collections may contain both value and reference types, including other collections.
46
+
39
47
  === Thread safety
40
48
 
41
49
  WARNING: In its current state the implemented collections are *not* thread-safe.
@@ -63,72 +71,70 @@ while(MyVectorItMove(&it)) {
63
71
  WARNING: the collection being iterated *must not* be modified in any way otherwise the iterator behavior is undefined.
64
72
  =end
65
73
  class Collection < Type
74
+
75
+ attr_reader :element, :it_ref
66
76
 
67
- def self.coerce(type)
68
- type.is_a?(Type) ? type : UserDefinedType.new(type)
69
- end
77
+ def hash; super ^ element.hash end
70
78
 
71
- attr_reader :element
79
+ def ==(other) super && element == other.element end
72
80
 
73
- def entities; super + [element] end
81
+ alias :eql? :==
82
+
83
+ def entities; super << element end
74
84
 
75
85
  def initialize(type_name, element_type, visibility = :public)
76
86
  super(type_name, visibility)
77
- @element = Collection.coerce(element_type)
87
+ @it_ref = "#{it}*"
88
+ @element = Type.coerce(element_type)
89
+ @ctor = define_function(:ctor, Function::Signature.new([type_ref^:self]))
90
+ @dtor = define_function(:dtor, Function::Signature.new([type_ref^:self]))
91
+ @copy = define_function(:copy, Function::Signature.new([type_ref^:dst, type_ref^:src]))
92
+ @equal = define_function(:equal, Function::Signature.new([type_ref^:lt, type_ref^:rt], :int))
93
+ @identify = define_function(:identify, Function::Signature.new([type_ref^:self], :size_t))
94
+ @less = define_function(:less, Function::Signature.new([type_ref^:lt, type_ref^:rt], :int))
95
+ element_type_check(element)
78
96
  end
79
97
 
80
- def ctor(*args)
81
- if args.empty?
82
- super()
83
- else
84
- check_args(args, 1)
85
- obj = args.first
86
- super() + "(&#{obj})"
87
- end
88
- end
89
-
90
- def dtor(*args)
91
- if args.empty?
92
- super()
93
- else
94
- check_args(args, 1)
95
- obj = args.first
96
- super() + "(&#{obj})"
97
- end
98
+ def write_intf_decls(stream, declare, define)
99
+ # Emit default redirection macros
100
+ # Unlike other special methods the constructors may have extra arguments
101
+ # Assume the constructor's first parameter is always a target
102
+ ctor_ex = ctor.parameters.names[1..-1]
103
+ ctor_lt = ["self"].concat(ctor_ex).join(',')
104
+ ctor_rt = ["&self"].concat(ctor_ex).join(',')
105
+ stream << %$
106
+ #define _#{ctor}(#{ctor_lt}) #{ctor}(#{ctor_rt})
107
+ #define _#{dtor}(self) #{dtor}(&self)
108
+ #define _#{identify}(self) #{identify}(&self)
109
+ #define _#{copy}(dst,src) #{copy}(&dst,&src)
110
+ #define _#{equal}(lt,rt) #{equal}(&lt,&rt)
111
+ #define _#{less}(lt,rt) #{less}(&lt,&rt)
112
+ $
98
113
  end
114
+
115
+ def copyable?; super && element.copyable? end
99
116
 
100
- def copy(*args)
101
- if args.empty?
102
- super()
103
- else
104
- check_args(args, 2)
105
- dst, src = args
106
- super() + "(&#{dst}, &#{src})"
107
- end
108
- end
117
+ def comparable?; super && element.comparable? end
109
118
 
110
- def equal(*args)
111
- if args.empty?
112
- super()
113
- else
114
- check_args(args, 2)
115
- lt, rt = args
116
- super() + "(&#{lt}, &#{rt})"
117
- end
118
- end
119
+ def hashable?; super && element.hashable? end
119
120
 
120
- def less(*args)
121
- args.empty? ? super() : raise("#{self.class} provides no ordering functionality")
122
- end
121
+ private
123
122
 
124
- def identify(*args)
125
- args.empty? ? super() : raise("#{self.class} provides no hashing functionality")
123
+ def element_type_check(obj)
124
+ raise "type #{obj.type} (#{obj}) must be destructible" unless obj.destructible?
125
+ raise "type #{obj.type} (#{obj}) must be copyable" unless obj.copyable?
126
+ raise "type #{obj.type} (#{obj}) must be comparable" unless obj.comparable?
127
+ raise "type #{obj.type} (#{obj}) must be hashable" unless obj.hashable?
126
128
  end
127
129
 
128
- private
130
+ # @private
131
+ class Redirector < Function
132
+ # Redirect call to the specific macro
133
+ def call(*params) "_#{name}(" + params.join(',') + ')' end
134
+ end # Redirector
129
135
 
130
- def check_args(args, nargs)
131
- raise "expected exactly #{nargs} argument(s)" unless args.size == nargs
136
+ def define_function(name, signature)
137
+ Redirector.new(method_missing(name), signature)
132
138
  end
133
139
 
134
140
  end # Collection
@@ -133,16 +133,35 @@ class HashMap < Collection
133
133
 
134
134
  alias :value :element
135
135
 
136
- def entities; super + [key] end
136
+ def hash; super ^ key.hash end
137
+
138
+ def ==(other) super && key == other.key end
139
+
140
+ alias :eql? :==
141
+
142
+ def entities; super << key end
137
143
 
138
144
  def initialize(type, key_type, value_type, visibility = :public)
139
145
  super(type, value_type, visibility)
140
- @key = Collection.coerce(key_type)
146
+ @key = Type.coerce(key_type)
141
147
  @entry = UserDefinedType.new(:type => entry, :identify => entryIdentify, :equal => entryEqual, :copy => entryCopy, :dtor => entryDtor)
142
148
  @set = HashSet.new(set, @entry, :static)
149
+ @capability.subtract [:orderable]
150
+ element_type_check(value)
151
+ key_type_check(key)
143
152
  end
144
153
 
145
- def write_exported_types(stream)
154
+ def copyable?; super && key.copyable? end
155
+
156
+ def comparable?; super && key.comparable? end
157
+
158
+ def hashable?
159
+ # NOTE : must be in sync with Type#hashable?
160
+ # No super call here because the map's element need not to be hashable,- only the key must be
161
+ @capability.include?(:hashable) && comparable? && key.hashable?
162
+ end
163
+
164
+ def write_intf_types(stream)
146
165
  stream << %$
147
166
  /***
148
167
  **** #{type}<#{key.type},#{value.type}> (#{self.class})
@@ -156,7 +175,7 @@ class HashMap < Collection
156
175
  unsigned flags;
157
176
  };
158
177
  $
159
- @set.write_exported_types(stream)
178
+ @set.write_intf_types(stream)
160
179
  stream << %$
161
180
  typedef struct #{type} #{type};
162
181
  typedef struct #{it} #{it};
@@ -169,42 +188,43 @@ class HashMap < Collection
169
188
  $
170
189
  end
171
190
 
172
- def write_exported_declarations(stream, declare, define)
191
+ def write_intf_decls(stream, declare, define)
192
+ super
173
193
  stream << %$
174
- #{declare} void #{ctor}(#{type}*);
175
- #{declare} void #{dtor}(#{type}*);
176
- #{declare} void #{copy}(#{type}*, #{type}*);
177
- #{declare} int #{equal}(#{type}*, #{type}*);
178
- #{declare} size_t #{identify}(#{type}*);
179
- #{declare} void #{purge}(#{type}*);
180
- #{declare} size_t #{size}(#{type}*);
194
+ #{declare} #{ctor.declaration};
195
+ #{declare} #{dtor.declaration};
196
+ #{declare} #{copy.declaration};
197
+ #{declare} #{equal.declaration};
198
+ #{declare} #{identify.declaration};
199
+ #{declare} void #{purge}(#{type_ref});
200
+ #{declare} size_t #{size}(#{type_ref});
181
201
  #define #{empty}(self) (#{size}(self) == 0)
182
- #{declare} int #{containsKey}(#{type}*, #{key.type});
183
- #{declare} #{value.type} #{get}(#{type}*, #{key.type});
184
- #{declare} int #{put}(#{type}*, #{key.type}, #{value.type});
185
- #{declare} int #{replace}(#{type}*, #{key.type}, #{value.type});
186
- #{declare} int #{remove}(#{type}*, #{key.type});
187
- #{declare} void #{itCtor}(#{it}*, #{type}*);
188
- #{declare} int #{itMove}(#{it}*);
189
- #{declare} #{key.type} #{itGetKey}(#{it}*);
190
- #{declare} #{value.type} #{itGetElement}(#{it}*);
202
+ #{declare} int #{containsKey}(#{type_ref}, #{key.type});
203
+ #{declare} #{value.type} #{get}(#{type_ref}, #{key.type});
204
+ #{declare} int #{put}(#{type_ref}, #{key.type}, #{value.type});
205
+ #{declare} int #{replace}(#{type_ref}, #{key.type}, #{value.type});
206
+ #{declare} int #{remove}(#{type_ref}, #{key.type});
207
+ #{declare} void #{itCtor}(#{it_ref}, #{type_ref});
208
+ #{declare} int #{itMove}(#{it_ref});
209
+ #{declare} #{key.type} #{itGetKey}(#{it_ref});
210
+ #{declare} #{value.type} #{itGetElement}(#{it_ref});
191
211
  #define #{itGet}(it) #{itGetElement}(it)
192
212
  $
193
213
  end
194
214
 
195
- def write_implementations(stream, define)
215
+ def write_impls(stream, define)
196
216
  stream << %$
197
217
  #define AUTOC_VALID_VALUE 1
198
218
  #define AUTOC_VALID_KEY 2
199
219
  #define AUTOC_OWNED_VALUE 4
200
220
  #define AUTOC_OWNED_KEY 8
201
- static #{@entry.type} #{entryKeyOnlyRef}(#{key.type}* key) {
221
+ static #{@entry.type} #{entryKeyOnlyRef}(#{key.type_ref} key) {
202
222
  #{@entry.type} entry;
203
223
  entry.key = *key;
204
224
  entry.flags = AUTOC_VALID_KEY;
205
225
  return entry;
206
226
  }
207
- static #{@entry.type} #{entryKeyValueRef}(#{key.type}* key, #{value.type}* value) {
227
+ static #{@entry.type} #{entryKeyValueRef}(#{key.type_ref} key, #{value.type_ref} value) {
208
228
  #{@entry.type} entry;
209
229
  entry.key = *key;
210
230
  entry.value = *value;
@@ -220,7 +240,7 @@ class HashMap < Collection
220
240
  return #{key.equal("lt->key", "rt->key")};
221
241
  }
222
242
  #define #{entryCopy}(dst, src) #{entryCopyRef}(&dst, &src)
223
- static void #{entryCopyRef}(#{@entry.type}* dst, #{@entry.type}* src) {
243
+ static void #{entryCopyRef}(#{@entry.type_ref} dst, #{@entry.type_ref} src) {
224
244
  #{assert}(src->flags & AUTOC_VALID_KEY);
225
245
  dst->flags = (AUTOC_VALID_KEY | AUTOC_OWNED_KEY);
226
246
  #{key.copy("dst->key", "src->key")};
@@ -235,20 +255,35 @@ class HashMap < Collection
235
255
  if(entry->flags & AUTOC_OWNED_KEY) #{key.dtor("entry->key")};
236
256
  if(entry->flags & AUTOC_VALID_VALUE && entry->flags & AUTOC_OWNED_VALUE) #{value.dtor("entry->value")};
237
257
  }
258
+ static #{@entry.type_ref} #{itGetEntryRef}(#{it_ref});
259
+ static int #{containsAllOf}(#{type_ref} self, #{type_ref} other) {
260
+ #{it} it;
261
+ #{itCtor}(&it, self);
262
+ while(#{itMove}(&it)) {
263
+ int found = 0;
264
+ #{@entry.type}* e = #{itGetEntryRef}(&it);
265
+ if(#{containsKey}(other, e->key)) {
266
+ #{value.type} other_value = #{get}(other, e->key);
267
+ found = #{value.equal("e->value", "other_value")};
268
+ #{value.dtor("other_value")};
269
+ }
270
+ if(!found) return 0;
271
+ }
272
+ return 1;
273
+ }
238
274
  $
239
- @set.write_exported_declarations(stream, static, inline)
240
- @set.write_implementations(stream, static)
275
+ @set.write_intf_decls(stream, static, inline)
276
+ @set.write_impls(stream, static)
241
277
  stream << %$
242
- static #{@entry.type}* #{itGetEntryRef}(#{it}*);
243
- #{define} void #{ctor}(#{type}* self) {
278
+ #{define} #{ctor.definition} {
244
279
  #{assert}(self);
245
280
  #{@set.ctor}(&self->entries);
246
281
  }
247
- #{define} void #{dtor}(#{type}* self) {
282
+ #{define} #{dtor.definition} {
248
283
  #{assert}(self);
249
284
  #{@set.dtor}(&self->entries);
250
285
  }
251
- static int #{putEntryRef}(#{type}* self, #{@entry.type}* entry) {
286
+ static int #{putEntryRef}(#{type_ref} self, #{@entry.type_ref} entry) {
252
287
  int absent;
253
288
  #{assert}(self);
254
289
  #{assert}(entry);
@@ -257,7 +292,7 @@ class HashMap < Collection
257
292
  }
258
293
  return absent;
259
294
  }
260
- #{define} void #{copy}(#{type}* dst, #{type}* src) {
295
+ #{define} #{copy.definition} {
261
296
  #{it} it;
262
297
  #{assert}(src);
263
298
  #{assert}(dst);
@@ -268,39 +303,24 @@ class HashMap < Collection
268
303
  #{putEntryRef}(dst, e);
269
304
  }
270
305
  }
271
- static int #{containsAllOf}(#{type}* self, #{type}* other) {
272
- #{it} it;
273
- #{itCtor}(&it, self);
274
- while(#{itMove}(&it)) {
275
- int found = 0;
276
- #{@entry.type}* e = #{itGetEntryRef}(&it);
277
- if(#{containsKey}(other, e->key)) {
278
- #{value.type} other_value = #{get}(other, e->key);
279
- found = #{value.equal("e->value", "other_value")};
280
- #{value.dtor("other_value")};
281
- }
282
- if(!found) return 0;
283
- }
284
- return 1;
285
- }
286
- #{define} int #{equal}(#{type}* lt, #{type}* rt) {
306
+ #{define} #{equal.definition} {
287
307
  #{assert}(lt);
288
308
  #{assert}(rt);
289
309
  return #{size}(lt) == #{size}(rt) && #{containsAllOf}(lt, rt) && #{containsAllOf}(rt, lt);
290
310
  }
291
- #{define} size_t #{identify}(#{type}* self) {
311
+ #{define} #{identify.definition} {
292
312
  #{assert}(self);
293
313
  return #{@set.identify}(&self->entries); /* TODO : make use of the values' hashes */
294
314
  }
295
- #{define} void #{purge}(#{type}* self) {
315
+ #{define} void #{purge}(#{type_ref} self) {
296
316
  #{assert}(self);
297
317
  #{@set.purge}(&self->entries);
298
318
  }
299
- #{define} size_t #{size}(#{type}* self) {
319
+ #{define} size_t #{size}(#{type_ref} self) {
300
320
  #{assert}(self);
301
321
  return #{@set.size}(&self->entries);
302
322
  }
303
- #{define} int #{containsKey}(#{type}* self, #{key.type} key) {
323
+ #{define} int #{containsKey}(#{type_ref} self, #{key.type} key) {
304
324
  int result;
305
325
  #{@entry.type} entry;
306
326
  #{assert}(self);
@@ -308,7 +328,7 @@ class HashMap < Collection
308
328
  #{@entry.dtor("entry")};
309
329
  return result;
310
330
  }
311
- #{define} #{value.type} #{get}(#{type}* self, #{key.type} key) {
331
+ #{define} #{value.type} #{get}(#{type_ref} self, #{key.type} key) {
312
332
  #{value.type} result;
313
333
  #{@entry.type} entry, existing_entry;
314
334
  #{assert}(self);
@@ -319,7 +339,7 @@ class HashMap < Collection
319
339
  #{@entry.dtor("entry")};
320
340
  return result;
321
341
  }
322
- #{define} int #{put}(#{type}* self, #{key.type} key, #{value.type} value) {
342
+ #{define} int #{put}(#{type_ref} self, #{key.type} key, #{value.type} value) {
323
343
  int result;
324
344
  #{@entry.type} entry;
325
345
  #{assert}(self);
@@ -328,7 +348,7 @@ class HashMap < Collection
328
348
  #{@entry.dtor("entry")};
329
349
  return result;
330
350
  }
331
- #{define} int #{replace}(#{type}* self, #{key.type} key, #{value.type} value) {
351
+ #{define} int #{replace}(#{type_ref} self, #{key.type} key, #{value.type} value) {
332
352
  int result;
333
353
  #{@entry.type} entry;
334
354
  #{assert}(self);
@@ -337,7 +357,7 @@ class HashMap < Collection
337
357
  #{@entry.dtor("entry")};
338
358
  return result;
339
359
  }
340
- #{define} int #{remove}(#{type}* self, #{key.type} key) {
360
+ #{define} int #{remove}(#{type_ref} self, #{key.type} key) {
341
361
  int result;
342
362
  #{@entry.type} entry;
343
363
  #{assert}(self);
@@ -345,25 +365,25 @@ class HashMap < Collection
345
365
  #{@entry.dtor("entry")};
346
366
  return result;
347
367
  }
348
- #{define} void #{itCtor}(#{it}* self, #{type}* map) {
368
+ #{define} void #{itCtor}(#{it_ref} self, #{type_ref} map) {
349
369
  #{assert}(self);
350
370
  #{assert}(map);
351
371
  #{@set.itCtor}(&self->it, &map->entries);
352
372
  }
353
- #{define} int #{itMove}(#{it}* self) {
373
+ #{define} int #{itMove}(#{it_ref} self) {
354
374
  #{assert}(self);
355
375
  return #{@set.itMove}(&self->it);
356
376
  }
357
- #{define} #{key.type} #{itGetKey}(#{it}* self) {
358
- #{@entry.type}* e;
377
+ #{define} #{key.type} #{itGetKey}(#{it_ref} self) {
378
+ #{@entry.type_ref} e;
359
379
  #{key.type} key;
360
380
  #{assert}(self);
361
381
  e = #{itGetEntryRef}(self);
362
382
  #{key.copy("key", "e->key")};
363
383
  return key;
364
384
  }
365
- #{define} #{value.type} #{itGetElement}(#{it}* self) {
366
- #{@entry.type}* e;
385
+ #{define} #{value.type} #{itGetElement}(#{it_ref} self) {
386
+ #{@entry.type_ref} e;
367
387
  #{value.type} value;
368
388
  #{assert}(self);
369
389
  e = #{itGetEntryRef}(self);
@@ -371,7 +391,7 @@ class HashMap < Collection
371
391
  #{value.copy("value", "e->value")};
372
392
  return value;
373
393
  }
374
- static #{@entry.type}* #{itGetEntryRef}(#{it}* self) {
394
+ static #{@entry.type_ref} #{itGetEntryRef}(#{it_ref} self) {
375
395
  #{assert}(self);
376
396
  return #{@set.itGetRef}(&self->it);
377
397
  }