autoc 1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +3 -1
- data/CHANGES +15 -0
- data/README +2 -0
- data/doc/AutoC.html +84 -14
- data/doc/AutoC/Code.html +31 -31
- data/doc/AutoC/Collection.html +250 -182
- data/doc/AutoC/HashMap.html +565 -245
- data/doc/AutoC/HashSet.html +266 -264
- data/doc/AutoC/List.html +317 -249
- data/doc/AutoC/Module.html +66 -72
- data/doc/AutoC/Module/File.html +25 -25
- data/doc/AutoC/Module/Header.html +25 -25
- data/doc/AutoC/Module/Source.html +43 -43
- data/doc/AutoC/Priority.html +3 -3
- data/doc/AutoC/Queue.html +352 -286
- data/doc/AutoC/Reference.html +578 -0
- data/doc/AutoC/Type.html +941 -131
- data/doc/AutoC/UserDefinedType.html +64 -313
- data/doc/AutoC/Vector.html +336 -306
- data/doc/_index.html +22 -4
- data/doc/class_list.html +6 -2
- data/doc/file.CHANGES.html +102 -0
- data/doc/file.README.html +7 -4
- data/doc/file_list.html +8 -1
- data/doc/frames.html +1 -1
- data/doc/index.html +7 -4
- data/doc/js/full_list.js +4 -1
- data/doc/method_list.html +236 -118
- data/doc/top-level-namespace.html +3 -3
- data/lib/autoc.rb +3 -3
- data/lib/autoc/code.rb +11 -5
- data/lib/autoc/collection.rb +62 -56
- data/lib/autoc/collection/hash_map.rb +83 -63
- data/lib/autoc/collection/hash_set.rb +74 -64
- data/lib/autoc/collection/list.rb +48 -41
- data/lib/autoc/collection/queue.rb +53 -47
- data/lib/autoc/collection/vector.rb +63 -42
- data/lib/autoc/type.rb +326 -61
- data/test/test.c +120 -0
- data/test/test.rb +16 -2
- data/test/test_auto.c +1683 -987
- data/test/test_auto.h +491 -176
- metadata +22 -19
data/lib/autoc/type.rb
CHANGED
@@ -1,9 +1,104 @@
|
|
1
|
+
require "set"
|
2
|
+
require "forwardable"
|
1
3
|
require "autoc/code"
|
2
4
|
|
3
5
|
|
4
6
|
module AutoC
|
5
7
|
|
6
8
|
|
9
|
+
# @private
|
10
|
+
class Dispatcher
|
11
|
+
|
12
|
+
# @private
|
13
|
+
class ParameterArray < Array
|
14
|
+
def self.coerce(*params)
|
15
|
+
out = []
|
16
|
+
i = 0
|
17
|
+
params.each do |t|
|
18
|
+
i += 1
|
19
|
+
out << (t.is_a?(Array) ? t.collect {|x| x.to_s} : [t.to_s, "_#{i}"])
|
20
|
+
end
|
21
|
+
self.new(out)
|
22
|
+
end
|
23
|
+
# Test for parameter list compatibility
|
24
|
+
def ===(other) other.is_a?(ParameterArray) && types == other.types end
|
25
|
+
def types; collect {|x| x.first} end
|
26
|
+
def names; collect {|x| x.last} end
|
27
|
+
def pass; names.join(',') end
|
28
|
+
def declaration; types.join(',') end
|
29
|
+
def definition; collect {|x| "#{x.first} #{x.last}"}.join(',') end
|
30
|
+
end # ParameterArray
|
31
|
+
|
32
|
+
# def call(*params)
|
33
|
+
|
34
|
+
def dispatch(*params)
|
35
|
+
if params.empty?
|
36
|
+
self
|
37
|
+
else
|
38
|
+
params = [] if params.size == 1 && params.first.nil?
|
39
|
+
call(*params)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end # Dispatcher
|
44
|
+
|
45
|
+
|
46
|
+
# @private
|
47
|
+
class Statement < Dispatcher
|
48
|
+
|
49
|
+
attr_reader :parameters
|
50
|
+
|
51
|
+
def initialize(params = [])
|
52
|
+
@parameters = ParameterArray.coerce(*params)
|
53
|
+
end
|
54
|
+
|
55
|
+
end # Statement
|
56
|
+
|
57
|
+
|
58
|
+
# @private
|
59
|
+
class Function < Dispatcher
|
60
|
+
|
61
|
+
# @private
|
62
|
+
class Signature
|
63
|
+
|
64
|
+
attr_reader :parameters, :result
|
65
|
+
|
66
|
+
def initialize(params = [], result = nil)
|
67
|
+
@parameters = Dispatcher::ParameterArray.coerce(*params)
|
68
|
+
@result = (result.nil? ? :void : result).to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
end # Signature
|
72
|
+
|
73
|
+
extend Forwardable
|
74
|
+
|
75
|
+
def_delegators :@signature,
|
76
|
+
:parameters, :result
|
77
|
+
|
78
|
+
attr_reader :name, :signature
|
79
|
+
|
80
|
+
def initialize(name, a = [], b = nil)
|
81
|
+
@name = AutoC.c_id(name)
|
82
|
+
@signature = a.is_a?(Signature) ? a : Signature.new(a, b)
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s; name end
|
86
|
+
|
87
|
+
def call(*params)
|
88
|
+
"#{name}(#{params.join(',')})"
|
89
|
+
end
|
90
|
+
|
91
|
+
def definition
|
92
|
+
"#{result} #{name}(#{parameters.definition})"
|
93
|
+
end
|
94
|
+
|
95
|
+
def declaration
|
96
|
+
"#{result} #{name}(#{parameters.declaration})"
|
97
|
+
end
|
98
|
+
|
99
|
+
end # Function
|
100
|
+
|
101
|
+
|
7
102
|
class Type < Code
|
8
103
|
|
9
104
|
# @private
|
@@ -50,60 +145,83 @@ class Type < Code
|
|
50
145
|
end
|
51
146
|
end.new
|
52
147
|
|
53
|
-
|
148
|
+
def self.coerce(type)
|
149
|
+
type.is_a?(Type) ? type : UserDefinedType.new(type)
|
150
|
+
end
|
151
|
+
|
152
|
+
def hash; self.class.hash ^ type.hash end
|
153
|
+
|
154
|
+
def ==(other) self.class == other.class && type == other.type end
|
54
155
|
|
55
|
-
|
156
|
+
alias :eql? :==
|
157
|
+
|
158
|
+
def entities; super << CommonCode end
|
56
159
|
|
160
|
+
attr_reader :type, :type_ref
|
161
|
+
|
162
|
+
def prefix
|
163
|
+
# Lazy evaluator for simple types like char* which do not actually use
|
164
|
+
# this method and hence do not require the prefix to be valid C identifier
|
165
|
+
AutoC.c_id(type)
|
166
|
+
end
|
167
|
+
|
57
168
|
def initialize(type, visibility = :public)
|
58
169
|
@type = type.to_s
|
170
|
+
@type_ref = "#{self.type}*"
|
59
171
|
@visibility = [:public, :private, :static].include?(visibility) ? visibility : raise("unsupported visibility")
|
172
|
+
@capability = Set[:constructible, :destructible, :copyable, :comparable, :hashable, :orderable] # Can be used to disable specific capabilities for a type
|
173
|
+
# Canonic special method signatures
|
174
|
+
@ctor_signature = Function::Signature.new([type^:self])
|
175
|
+
@dtor_signature = Function::Signature.new([type^:self])
|
176
|
+
@copy_signature = Function::Signature.new([type^:dst, type^:src])
|
177
|
+
@equal_signature = Function::Signature.new([type^:lt, type^:rt], :int)
|
178
|
+
@identify_signature = Function::Signature.new([type^:self], :size_t)
|
179
|
+
@less_signature = Function::Signature.new([type^:lt, type^:rt], :int)
|
60
180
|
end
|
61
181
|
|
62
182
|
def method_missing(method, *args)
|
63
183
|
str = method.to_s
|
64
|
-
|
184
|
+
str = str.sub(/[\!\?]$/, '') # Strip trailing ? or !
|
185
|
+
fn = prefix + str[0,1].capitalize + str[1..-1] # Ruby 1.8 compatible
|
65
186
|
if args.empty?
|
66
|
-
|
187
|
+
fn # Emit bare function name
|
67
188
|
elsif args.size == 1 && args.first == nil
|
68
|
-
|
189
|
+
fn + '()' # Use sole nil argument to emit function call with no arguments
|
69
190
|
else
|
70
|
-
|
191
|
+
fn + '(' + args.join(',') + ')' # Emit normal function call with supplied arguments
|
71
192
|
end
|
72
193
|
end
|
73
194
|
|
74
195
|
def write_intf(stream)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
write_exported_declarations(stream, extern, inline)
|
196
|
+
if public?
|
197
|
+
write_intf_types(stream)
|
198
|
+
write_intf_decls(stream, extern, inline)
|
79
199
|
end
|
80
200
|
end
|
81
201
|
|
82
202
|
def write_decls(stream)
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
write_exported_declarations(stream, static, inline)
|
203
|
+
if private?
|
204
|
+
write_intf_types(stream)
|
205
|
+
write_intf_decls(stream, extern, inline)
|
206
|
+
elsif static?
|
207
|
+
write_intf_types(stream)
|
208
|
+
write_intf_decls(stream, static, inline)
|
90
209
|
end
|
91
210
|
end
|
92
211
|
|
93
212
|
def write_defs(stream)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
write_implementations(stream, static)
|
213
|
+
if public? || private?
|
214
|
+
write_impls(stream, nil)
|
215
|
+
elsif static?
|
216
|
+
write_impls(stream, static)
|
99
217
|
end
|
100
218
|
end
|
101
219
|
|
102
|
-
def
|
220
|
+
# def write_intf_types(stream)
|
103
221
|
|
104
|
-
def
|
222
|
+
# def write_intf_decls(stream, declare, define)
|
105
223
|
|
106
|
-
def
|
224
|
+
# def write_impls(stream, define)
|
107
225
|
|
108
226
|
def extern; "AUTOC_EXTERN" end
|
109
227
|
|
@@ -121,78 +239,225 @@ class Type < Code
|
|
121
239
|
|
122
240
|
def abort; "abort" end
|
123
241
|
|
124
|
-
protected
|
125
|
-
|
126
242
|
def public?; @visibility == :public end
|
127
243
|
|
128
244
|
def private?; @visibility == :private end
|
129
245
|
|
130
246
|
def static?; @visibility == :static end
|
131
247
|
|
248
|
+
def constructible?; @capability.include?(:constructible) end
|
249
|
+
|
250
|
+
def destructible?; @capability.include?(:destructible) end
|
251
|
+
|
252
|
+
def copyable?; @capability.include?(:copyable) end
|
253
|
+
|
254
|
+
def comparable?; @capability.include?(:comparable) end
|
255
|
+
|
256
|
+
def orderable?; @capability.include?(:orderable) && comparable? end
|
257
|
+
|
258
|
+
def hashable?; @capability.include?(:hashable) && comparable? end
|
259
|
+
|
260
|
+
# Create forwarding readers which take arbitrary number of arguments
|
261
|
+
[:ctor, :dtor, :copy, :equal, :identify, :less].each do |name|
|
262
|
+
class_eval %$
|
263
|
+
def #{name}(*args)
|
264
|
+
@#{name}.dispatch(*args)
|
265
|
+
end
|
266
|
+
$
|
267
|
+
end
|
268
|
+
|
269
|
+
private
|
270
|
+
|
271
|
+
def define_function(name, signature)
|
272
|
+
Function.new(method_missing(name), signature)
|
273
|
+
end
|
274
|
+
|
132
275
|
end # Type
|
133
276
|
|
134
277
|
|
278
|
+
=begin
|
279
|
+
|
280
|
+
UserDefinedType represents a user-defined custom type.
|
281
|
+
|
282
|
+
=end
|
135
283
|
class UserDefinedType < Type
|
136
284
|
|
137
285
|
# @private
|
138
286
|
class PublicDeclaration < Code
|
139
|
-
def entities; super
|
287
|
+
def entities; super << Type::CommonCode end
|
140
288
|
def initialize(forward) @forward = forward.to_s end
|
141
289
|
def hash; @forward.hash end
|
142
|
-
def
|
290
|
+
def ==(other) self.class == other.class && @forward == other.instance_variable_get(:@forward) end
|
291
|
+
alias :eql? :==
|
143
292
|
def write_intf(stream)
|
144
|
-
stream << "\n"
|
145
|
-
stream << @forward
|
146
|
-
stream << "\n"
|
293
|
+
stream << "\n#{@forward}\n"
|
147
294
|
end
|
148
295
|
end # PublicDeclaration
|
149
296
|
|
150
|
-
def entities; super
|
297
|
+
def entities; super.concat(@deps) end
|
298
|
+
|
299
|
+
def prefix; @prefix.nil? ? super : @prefix end
|
151
300
|
|
152
301
|
def initialize(opt)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
t = opt
|
157
|
-
elsif opt.is_a?(Hash)
|
158
|
-
t = opt[:type].nil? ? raise("type is not specified") : opt[:type]
|
159
|
-
[:ctor, :dtor, :copy, :equal, :less, :identify].each do |key|
|
160
|
-
instance_variable_set("@#{key}".to_sym, opt[key].to_s) unless opt[key].nil?
|
161
|
-
end
|
162
|
-
@deps << PublicDeclaration.new(opt[:forward]) unless opt[:forward].nil?
|
163
|
-
optv = opt[:visibility]
|
164
|
-
v = optv.nil? ? :public : optv
|
302
|
+
opt = {:type => opt} if opt.is_a?(Symbol) || opt.is_a?(String)
|
303
|
+
if opt.is_a?(Hash)
|
304
|
+
t = opt[:type].nil? ? raise("type is not specified") : opt[:type].to_s
|
165
305
|
else
|
166
|
-
raise "
|
306
|
+
raise "argument must be a Symbol, String or Hash"
|
167
307
|
end
|
168
|
-
super(t
|
308
|
+
super(t)
|
309
|
+
@prefix = AutoC.c_id(opt[:prefix]) unless opt[:prefix].nil?
|
310
|
+
@deps = []; @deps << PublicDeclaration.new(opt[:forward]) unless opt[:forward].nil?
|
311
|
+
opt.default = :unset # This allows to use nil as a value to indicate that the specific method is not avaliable
|
312
|
+
opt[:ctor].nil? ? @capability.subtract([:constructible]) : define_callable(:ctor, opt) {def call(obj) "((#{obj}) = 0)" end}
|
313
|
+
opt[:dtor].nil? ? @capability.subtract([:destructible]) : define_callable(:dtor, opt) {def call(obj) end}
|
314
|
+
opt[:copy].nil? ? @capability.subtract([:copyable]) : define_callable(:copy, opt) {def call(dst, src) "((#{dst}) = (#{src}))" end}
|
315
|
+
opt[:equal].nil? ? @capability.subtract([:comparable]) : define_callable(:equal, opt) {def call(lt, rt) "((#{lt}) == (#{rt}))" end}
|
316
|
+
opt[:less].nil? ? @capability.subtract([:orderable]) : define_callable(:less, opt) {def call(lt, rt) "((#{lt}) < (#{rt}))" end}
|
317
|
+
opt[:identify].nil? ? @capability.subtract([:hashable]) : define_callable(:identify, opt) {def call(obj) "((size_t)(#{obj}))" end}
|
318
|
+
# Handle specific requirements
|
319
|
+
@capability.subtract([:constructible]) if @ctor.parameters.size > 1 # Constructible type must not have extra parameters besides self
|
169
320
|
end
|
170
321
|
|
171
|
-
|
172
|
-
@ctor.nil? ? "(#{obj} = 0)" : "#{@ctor}(#{obj})"
|
173
|
-
end
|
322
|
+
private
|
174
323
|
|
175
|
-
|
176
|
-
|
324
|
+
# Default methods creator
|
325
|
+
def define_callable(name, opt, &code)
|
326
|
+
iv = "@#{name}"
|
327
|
+
ivs = "@#{name}_signature"
|
328
|
+
c = if opt[name] == :unset
|
329
|
+
# Synthesize statement block with default (canonic) parameter list
|
330
|
+
Class.new(Statement, &code).new(instance_variable_get(ivs).parameters)
|
331
|
+
elsif opt[name].is_a?(Function)
|
332
|
+
opt[name] # If a Function instance is given, pass it through
|
333
|
+
else
|
334
|
+
# If only a name is specified, assume it is the function name with default signature
|
335
|
+
Function.new(opt[name], instance_variable_get(ivs))
|
336
|
+
end
|
337
|
+
instance_variable_set(iv, c)
|
177
338
|
end
|
178
339
|
|
179
|
-
|
180
|
-
|
340
|
+
end # UserDefinedType
|
341
|
+
|
342
|
+
|
343
|
+
=begin
|
344
|
+
|
345
|
+
Reference represents a managed counted reference for any type.
|
346
|
+
It can be used with any type, including AutoC collections themselves.
|
347
|
+
|
348
|
+
== Generated C interface
|
349
|
+
|
350
|
+
=== Type management
|
351
|
+
|
352
|
+
[cols="2*"]
|
353
|
+
|===
|
354
|
+
|*_Type_* * ~type~New(...)
|
355
|
+
|
|
356
|
+
Create and return a reference to *_Type_* with reference count set to one.
|
357
|
+
|
358
|
+
The storage for the returned instance is malloc()'ed. The instance is constructed with the type's constructor ~type~Ctor(...).
|
359
|
+
|
360
|
+
NOTE: The generated method borrows the second and subsequent arguments from the respective constructor.
|
361
|
+
|
362
|
+
|*_Type_* * ~type~Ref(*_Type_* * self)
|
363
|
+
|
|
364
|
+
Increment the +self+'s reference count and return +self+.
|
365
|
+
|
366
|
+
|*_void_* ~type~Free(*_Type_* * self)
|
367
|
+
|
|
368
|
+
Decrement the +self+'s reference count.
|
369
|
+
If the reference count reaches zero, free the storage and destroy the instance with the type's destructor ~type~Dtor().
|
370
|
+
|
371
|
+
=end
|
372
|
+
class Reference < Type
|
373
|
+
|
374
|
+
extend Forwardable
|
375
|
+
|
376
|
+
def_delegators :@target,
|
377
|
+
:prefix,
|
378
|
+
:public?, :private?, :static?,
|
379
|
+
:constructible?, :destructible?, :copyable?, :comparable?, :orderable?, :hashable?
|
380
|
+
|
381
|
+
def initialize(target)
|
382
|
+
@target = Type.coerce(target)
|
383
|
+
super(@target.type_ref) # NOTE : the type of the Reference instance itself is actually a pointer type
|
384
|
+
@ctor_params = Dispatcher::ParameterArray.new(@target.ctor.parameters[1..-1]) # Capture extra parameters from the target type constructor
|
385
|
+
define_callable(:ctor, @ctor_params) {def call(obj, *params) "((#{obj}) = #{@ref.new?}(#{params.join(',')}))" end}
|
386
|
+
define_callable(:dtor, [type]) {def call(obj) "#{@ref.free?}(#{obj})" end}
|
387
|
+
define_callable(:copy, [type, type]) {def call(dst, src) "((#{dst}) = #{@ref.ref?}(#{src}))" end}
|
388
|
+
define_callable(:equal, [type, type]) {def call(lt, rt) @target.equal("*#{lt}", "*#{rt}") end}
|
389
|
+
define_callable(:less, [type, type]) {def call(lt, rt) @target.less("*#{lt}", "*#{rt}") end}
|
390
|
+
define_callable(:identify, [type]) {def call(obj) @target.identify("*#{obj}") end}
|
181
391
|
end
|
182
392
|
|
183
|
-
def
|
184
|
-
|
393
|
+
def ==(other) @target == other.instance_variable_get(:@target) end
|
394
|
+
|
395
|
+
alias :eql? :==
|
396
|
+
|
397
|
+
def entities; super << @target end
|
398
|
+
|
399
|
+
def write_intf_decls(stream, declare, define)
|
400
|
+
stream << %$
|
401
|
+
/***
|
402
|
+
**** <#{type}> (#{self.class})
|
403
|
+
***/
|
404
|
+
#{declare} #{type} #{new?}(#{@ctor_params.declaration});
|
405
|
+
#{declare} #{type} #{ref?}(#{type});
|
406
|
+
#{declare} void #{free?}(#{type});
|
407
|
+
$
|
185
408
|
end
|
186
409
|
|
187
|
-
def
|
188
|
-
|
410
|
+
def write_impls(stream, define)
|
411
|
+
stream << %$
|
412
|
+
#define AUTOC_COUNTER(p) (*(size_t*)((char*)(p) + sizeof(#{@target.type})))
|
413
|
+
#{define} #{type} #{new?}(#{@ctor_params.definition}) {
|
414
|
+
#{type} self = (#{type})#{malloc}(sizeof(#{@target.type}) + sizeof(size_t)); #{assert}(self);
|
415
|
+
#{@target.ctor("*self", *@ctor_params.names)};
|
416
|
+
AUTOC_COUNTER(self) = 1;
|
417
|
+
return self;
|
418
|
+
}
|
419
|
+
#{define} #{type} #{ref?}(#{type} self) {
|
420
|
+
#{assert}(self);
|
421
|
+
++AUTOC_COUNTER(self);
|
422
|
+
return self;
|
423
|
+
}
|
424
|
+
#{define} void #{free?}(#{type} self) {
|
425
|
+
#{assert}(self);
|
426
|
+
if(--AUTOC_COUNTER(self) == 0) {
|
427
|
+
#{@target.dtor("*self")};
|
428
|
+
#{free}(self);
|
429
|
+
}
|
430
|
+
}
|
431
|
+
#undef AUTOC_COUNTER
|
432
|
+
$
|
189
433
|
end
|
190
434
|
|
191
|
-
|
192
|
-
|
435
|
+
private
|
436
|
+
|
437
|
+
# @private
|
438
|
+
class BoundStatement < Statement
|
439
|
+
def initialize(ref, target, params)
|
440
|
+
super(params)
|
441
|
+
@ref = ref
|
442
|
+
@target = target
|
443
|
+
end
|
444
|
+
end # BoundStatement
|
445
|
+
|
446
|
+
def define_callable(name, params, &code)
|
447
|
+
instance_variable_set("@#{name}", Class.new(BoundStatement, &code).new(self, @target, params))
|
193
448
|
end
|
194
449
|
|
195
|
-
end #
|
450
|
+
end # Reference
|
451
|
+
|
452
|
+
|
453
|
+
# Class adjustments for the function signature definition DSL
|
454
|
+
[Symbol, String, Type].each do |type|
|
455
|
+
type.class_eval do
|
456
|
+
def ^(name)
|
457
|
+
[self, name]
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
196
461
|
|
197
462
|
|
198
463
|
end # AutoC
|