autoc 1.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGES.md +3 -0
- data/README.md +149 -0
- data/cmake/AutoC.cmake +39 -0
- data/lib/autoc/allocators.rb +51 -0
- data/lib/autoc/association.rb +126 -0
- data/lib/autoc/box.rb +311 -0
- data/lib/autoc/cmake.rb +54 -0
- data/lib/autoc/collection.rb +83 -110
- data/lib/autoc/composite.rb +333 -0
- data/lib/autoc/cstring.rb +263 -0
- data/lib/autoc/function.rb +247 -0
- data/lib/autoc/hash_map.rb +328 -0
- data/lib/autoc/hash_set.rb +339 -0
- data/lib/autoc/hashers.rb +102 -0
- data/lib/autoc/list.rb +444 -0
- data/lib/autoc/module.rb +434 -0
- data/lib/autoc/openmp.rb +15 -0
- data/lib/autoc/primitive.rb +27 -0
- data/lib/autoc/ranges.rb +707 -0
- data/lib/autoc/record.rb +247 -0
- data/lib/autoc/scaffold/docs.rb +117 -0
- data/lib/autoc/scaffold/generic_value.rb +86 -0
- data/lib/autoc/scaffold/project.rb +75 -0
- data/lib/autoc/scaffold/test_cstring.rb +113 -0
- data/lib/autoc/scaffold/test_cstring_hash_set.rb +35 -0
- data/lib/autoc/scaffold/test_int_box.rb +22 -0
- data/lib/autoc/scaffold/test_int_hash_set.rb +448 -0
- data/lib/autoc/scaffold/test_int_list.rb +106 -0
- data/lib/autoc/scaffold/test_int_vector.rb +83 -0
- data/lib/autoc/scaffold/test_v2v_hash_map.rb +83 -0
- data/lib/autoc/scaffold/test_value_hash_set.rb +60 -0
- data/lib/autoc/scaffold/test_value_vector.rb +146 -0
- data/{test/test.rb → lib/autoc/scaffold/tests.rb} +179 -158
- data/lib/autoc/scaffold.rb +12 -0
- data/lib/autoc/sequential.rb +99 -0
- data/lib/autoc/set.rb +331 -0
- data/lib/autoc/std.rb +149 -0
- data/lib/autoc/type.rb +93 -531
- data/lib/autoc/vector.rb +290 -0
- data/lib/autoc.rb +4 -35
- metadata +55 -85
- data/.yardopts +0 -4
- data/CHANGES +0 -23
- data/README +0 -28
- data/doc/AutoC/Code.html +0 -523
- data/doc/AutoC/Collection.html +0 -1214
- data/doc/AutoC/HashMap.html +0 -1441
- data/doc/AutoC/HashSet.html +0 -916
- data/doc/AutoC/Iterators/Bidirectional.html +0 -204
- data/doc/AutoC/Iterators/Unidirectional.html +0 -200
- data/doc/AutoC/Iterators.html +0 -126
- data/doc/AutoC/List.html +0 -1039
- data/doc/AutoC/Maps.html +0 -290
- data/doc/AutoC/Module/File.html +0 -415
- data/doc/AutoC/Module/Header.html +0 -437
- data/doc/AutoC/Module/Source.html +0 -707
- data/doc/AutoC/Module.html +0 -948
- data/doc/AutoC/Priority.html +0 -138
- data/doc/AutoC/Queue.html +0 -1172
- data/doc/AutoC/Reference.html +0 -735
- data/doc/AutoC/Sets.html +0 -520
- data/doc/AutoC/String.html +0 -1394
- data/doc/AutoC/TreeMap.html +0 -1565
- data/doc/AutoC/TreeSet.html +0 -1447
- data/doc/AutoC/Type.html +0 -2148
- data/doc/AutoC/UserDefinedType.html +0 -1047
- data/doc/AutoC/Vector.html +0 -987
- data/doc/AutoC.html +0 -331
- data/doc/_index.html +0 -388
- data/doc/class_list.html +0 -51
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -58
- data/doc/css/style.css +0 -481
- data/doc/file.CHANGES.html +0 -117
- data/doc/file.README.html +0 -116
- data/doc/file_list.html +0 -61
- data/doc/frames.html +0 -17
- data/doc/index.html +0 -116
- data/doc/js/app.js +0 -243
- data/doc/js/full_list.js +0 -216
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -1307
- data/doc/top-level-namespace.html +0 -112
- data/lib/autoc/code.rb +0 -237
- data/lib/autoc/collection/hash_map.rb +0 -385
- data/lib/autoc/collection/hash_set.rb +0 -337
- data/lib/autoc/collection/iterator.rb +0 -39
- data/lib/autoc/collection/list.rb +0 -429
- data/lib/autoc/collection/map.rb +0 -41
- data/lib/autoc/collection/queue.rb +0 -517
- data/lib/autoc/collection/set.rb +0 -134
- data/lib/autoc/collection/tree_map.rb +0 -464
- data/lib/autoc/collection/tree_set.rb +0 -611
- data/lib/autoc/collection/vector.rb +0 -336
- data/lib/autoc/string.rb +0 -492
- data/test/test_auto.c +0 -7141
- data/test/test_auto.h +0 -753
- data/test/test_char_string.rb +0 -270
- data/test/test_int_list.rb +0 -35
- data/test/test_int_tree_set.rb +0 -111
- data/test/test_int_vector.rb +0 -34
- data/test/test_value_hash_map.rb +0 -162
- data/test/test_value_hash_set.rb +0 -173
- data/test/test_value_list.rb +0 -193
- data/test/test_value_queue.rb +0 -275
- data/test/test_value_tree_map.rb +0 -176
- data/test/test_value_tree_set.rb +0 -173
- data/test/test_value_vector.rb +0 -155
- data/test/value.rb +0 -80
data/lib/autoc/cmake.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
require 'digest'
|
5
|
+
require 'autoc/module'
|
6
|
+
|
7
|
+
|
8
|
+
module AutoC
|
9
|
+
|
10
|
+
|
11
|
+
# CMake package renderer for the AutoC module
|
12
|
+
class CMake
|
13
|
+
|
14
|
+
attr_reader :module
|
15
|
+
|
16
|
+
def file_name = "#{self.module.name}.cmake"
|
17
|
+
|
18
|
+
def initialize(m) = @module = m
|
19
|
+
|
20
|
+
def render
|
21
|
+
m = self.module
|
22
|
+
sources = self.module.sources.collect { |s| "${CMAKE_CURRENT_SOURCE_DIR}/#{s.file_name}" } .join(' ')
|
23
|
+
stream = %{
|
24
|
+
set(#{m.name}_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/#{m.header.file_name})
|
25
|
+
set(#{m.name}_SOURCES #{sources})
|
26
|
+
add_library(#{m.name} OBJECT ${#{m.name}_SOURCES})
|
27
|
+
target_include_directories(#{m.name} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
28
|
+
}
|
29
|
+
unless Digest::MD5.digest(stream) == (Digest::MD5.digest(File.read(file_name)) rescue nil)
|
30
|
+
File.write(file_name, stream)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.render(m) = self.new(m).render
|
35
|
+
|
36
|
+
end # CMake
|
37
|
+
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
### On code generation vs. CMake
|
43
|
+
|
44
|
+
# https://here-be-braces.com/integrating-a-flexible-code-generator-into-cmake/
|
45
|
+
# https://blog.kangz.net/posts/2016/05/26/integrating-a-code-generator-with-cmake/
|
46
|
+
|
47
|
+
|
48
|
+
### On code packaging
|
49
|
+
|
50
|
+
# https://www.youtube.com/watch?v=sBP17HQAQjk
|
51
|
+
# https://www.youtube.com/watch?v=_5weX5mx8hc
|
52
|
+
|
53
|
+
# https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html
|
54
|
+
# https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html
|
data/lib/autoc/collection.rb
CHANGED
@@ -1,145 +1,118 @@
|
|
1
|
-
|
2
|
-
require "autoc/type"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
=begin
|
4
|
+
require 'autoc/std'
|
5
|
+
require 'autoc/composite'
|
9
6
|
|
10
|
-
== Implemented types
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
- {AutoC::Reference} counted reference type
|
8
|
+
module AutoC
|
15
9
|
|
16
|
-
- {AutoC::String} string builder type with value semantics
|
17
10
|
|
18
|
-
|
11
|
+
using STD::Coercions
|
12
|
+
|
19
13
|
|
20
|
-
|
14
|
+
# @abstract
|
15
|
+
# Generator for C types which contain zero or more elements of a particular type
|
16
|
+
class Collection < Composite
|
21
17
|
|
22
|
-
|
18
|
+
attr_reader :element
|
23
19
|
|
24
|
-
|
20
|
+
attr_reader :range
|
25
21
|
|
26
|
-
|
22
|
+
def self.new(*args, **kws)
|
23
|
+
obj = super
|
24
|
+
obj.references << obj.range # Range has to be referenced after the iterable object gets fully configured
|
25
|
+
obj
|
26
|
+
end
|
27
27
|
|
28
|
-
|
28
|
+
def initialize(signature, element, **kws)
|
29
|
+
super(signature, **kws)
|
30
|
+
dependencies << (@element = element.to_type)
|
31
|
+
end
|
29
32
|
|
30
|
-
|
33
|
+
# For container to be copyable a copyable element type is required
|
34
|
+
def copyable? = super && element.copyable?
|
31
35
|
|
32
|
-
|
36
|
+
# For container to be comparable a comparable element type is required
|
37
|
+
def comparable? = super && element.comparable?
|
33
38
|
|
34
|
-
|
39
|
+
# For container to be orderable an orderable element type is required
|
40
|
+
def orderable? = super && element.orderable?
|
35
41
|
|
36
|
-
|
37
|
-
|
38
|
-
----
|
39
|
-
require "autoc"
|
40
|
-
AutoC::Module.generate!(:Test) do |c|
|
41
|
-
c << AutoC::List.new(:IntList, :int)
|
42
|
-
end
|
43
|
-
----
|
44
|
-
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.
|
45
|
-
The C++ counterpart of the generated collection is +std::forward_list<int>+.
|
42
|
+
# A destructible element type mandates creation of the container's destructor
|
43
|
+
def destructible? = super || element.destructible?
|
46
44
|
|
47
|
-
|
45
|
+
# For container to be hashable a hashable element type is required
|
46
|
+
def hashable? = super && element.hashable?
|
47
|
+
|
48
|
+
def type_tag = "#{signature}<#{element}>"
|
48
49
|
|
49
|
-
|
50
|
+
private
|
50
51
|
|
51
|
-
|
52
|
+
def configure
|
53
|
+
super
|
54
|
+
method(:int, :empty, { target: const_rvalue })
|
55
|
+
method(:size_t, :size, { target: const_rvalue })
|
56
|
+
# Separate certain methods creation from documenting due to mutual dependency
|
57
|
+
empty.configure do
|
58
|
+
header %{
|
59
|
+
@brief Check container for emptiness
|
52
60
|
|
53
|
-
|
61
|
+
@param[in] target container to check
|
62
|
+
@return non-zero value if container is empty (i.e. contains no elements) and zero value otherwise
|
54
63
|
|
55
|
-
|
64
|
+
@note This function's behavior must be consistent with @ref #{size}.
|
56
65
|
|
57
|
-
|
66
|
+
@since 2.0
|
67
|
+
}
|
68
|
+
end
|
69
|
+
size.configure do
|
70
|
+
header %{
|
71
|
+
@brief Return number of contained elements
|
58
72
|
|
59
|
-
|
60
|
-
|
61
|
-
All implemented iterators do not require destruction after use.
|
73
|
+
@param[in] target container to query
|
74
|
+
@return number of contained elements
|
62
75
|
|
63
|
-
|
64
|
-
[source,c]
|
65
|
-
----
|
66
|
-
MyVector c;
|
67
|
-
MyVectorIt it;
|
68
|
-
...
|
69
|
-
MyVectorItCtor(&it, &c);
|
70
|
-
while(MyVectorItMove(&it)) {
|
71
|
-
Element e = MyVectorItGet(&it);
|
72
|
-
...
|
73
|
-
ElementDtor(e);
|
74
|
-
}
|
75
|
-
----
|
76
|
+
@note This function's behavior must be consistent with @ref #{empty}.
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
|
78
|
+
@since 2.0
|
79
|
+
}
|
80
|
+
end
|
81
|
+
method(:int, :contains, { target: const_rvalue, value: element.const_rvalue }, constraint:-> { element.comparable? }).configure do
|
82
|
+
header %{
|
83
|
+
@brief Look up for specific element in container
|
80
84
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
def hash; super ^ element.hash end
|
86
|
-
|
87
|
-
def ==(other) super && element == other.element end
|
88
|
-
|
89
|
-
alias :eql? :==
|
85
|
+
@param[in] target container to query
|
86
|
+
@param[in] value element to look for
|
87
|
+
@return non-zero value if container has (at least one) element equal to the specified value and zero value otherwise
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
def initialize(type_name, element_type, visibility = :public)
|
94
|
-
super(type_name, visibility)
|
95
|
-
@it_ref = "#{it}*"
|
96
|
-
@element = Type.coerce(element_type)
|
97
|
-
initialize_redirectors
|
98
|
-
element_requirement(element)
|
99
|
-
end
|
100
|
-
|
101
|
-
# Normally all collections are expected to provide all special functions
|
102
|
-
# If a collection does not provide specific function it should override the respective method
|
103
|
-
|
104
|
-
# Collection always has default constructor
|
105
|
-
def constructible?; true end
|
89
|
+
This function scans through the container's contents to look for an element which is considered equal to the specified value.
|
90
|
+
The equality testing is performed with the element type's equality criterion.
|
106
91
|
|
107
|
-
|
108
|
-
|
92
|
+
@since 2.0
|
93
|
+
}
|
94
|
+
end
|
95
|
+
method(element.const_lvalue, :find_first, { target: const_rvalue, value: element.const_rvalue }, constraint:-> { element.comparable? }).configure do
|
96
|
+
header %{
|
97
|
+
@brief Search for specific element
|
109
98
|
|
110
|
-
|
111
|
-
|
112
|
-
|
99
|
+
@param[in] target container to search through
|
100
|
+
@param[in] value value to look for
|
101
|
+
@return a view of element equivalent to specified value or NULL value
|
113
102
|
|
114
|
-
|
115
|
-
|
116
|
-
def copyable?; true && element.copyable? end
|
103
|
+
This function scans through `target` and returns a constant reference (in form of the C pointer)
|
104
|
+
a contained element equivalent to the specified `target` or NULL value is there is no such element.
|
117
105
|
|
118
|
-
|
119
|
-
# because collection comparison incurs comparison of all contained elements
|
120
|
-
def comparable?; true && element.comparable? end
|
106
|
+
This function usually (but not neccessarily) yields first suitable element.
|
121
107
|
|
122
|
-
|
108
|
+
This function requires the element type to be *comparable* (i.e. to have a well-defined comparison operation).
|
123
109
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
comparable? && element.hashable?
|
129
|
-
end
|
110
|
+
@since 2.0
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
130
114
|
|
131
|
-
|
132
|
-
write_redirectors(stream, declare, define)
|
133
|
-
end
|
134
|
-
|
135
|
-
private
|
136
|
-
|
137
|
-
def element_requirement(obj)
|
138
|
-
raise "type #{obj.type} (#{obj}) must be destructible" unless obj.destructible?
|
139
|
-
raise "type #{obj.type} (#{obj}) must be copyable" unless obj.copyable?
|
140
|
-
end
|
141
|
-
|
142
|
-
end # Collection
|
115
|
+
end # Collection
|
143
116
|
|
144
117
|
|
145
|
-
end
|
118
|
+
end
|
@@ -0,0 +1,333 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
require 'autoc/std'
|
5
|
+
require 'autoc/type'
|
6
|
+
require 'autoc/module'
|
7
|
+
require 'autoc/hashers'
|
8
|
+
require 'autoc/allocators'
|
9
|
+
require 'autoc/function'
|
10
|
+
|
11
|
+
|
12
|
+
module AutoC
|
13
|
+
|
14
|
+
|
15
|
+
using STD::Coercions
|
16
|
+
|
17
|
+
|
18
|
+
# @abstract
|
19
|
+
class Composite < Type
|
20
|
+
|
21
|
+
PRIVATE = '/** @private */'
|
22
|
+
|
23
|
+
include STD
|
24
|
+
|
25
|
+
include Entity
|
26
|
+
|
27
|
+
attr_reader :visibility
|
28
|
+
|
29
|
+
attr_reader :_master # Internal reference to the containing type if this type is used as implementing type
|
30
|
+
|
31
|
+
def initialize(signature, visibility: :public, decorator: nil, allocator: nil, hasher: nil, _master: nil)
|
32
|
+
super(signature)
|
33
|
+
@methods = {}
|
34
|
+
@hasher = hasher
|
35
|
+
@decorator = decorator
|
36
|
+
@allocator = allocator
|
37
|
+
@visibility = visibility
|
38
|
+
dependencies << DEFINITIONS << ASSERT_H << self.memory << self.hasher
|
39
|
+
@_master = _master
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.new(*args, **kws, &block)
|
43
|
+
obj = super
|
44
|
+
obj.send(:configure)
|
45
|
+
obj
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_value = Value.new(self)
|
49
|
+
|
50
|
+
def rvalue = @rv ||= Value.new(self, reference: true)
|
51
|
+
|
52
|
+
def lvalue = @lv ||= Value.new(self, reference: true)
|
53
|
+
|
54
|
+
def const_rvalue = @crv ||= Value.new(self, constant: true, reference: true)
|
55
|
+
|
56
|
+
def const_lvalue = @clv ||= Value.new(self, constant: true, reference: true)
|
57
|
+
|
58
|
+
# Prefix used to generate type-qualified identifiers
|
59
|
+
# By default it returns the C side type signature but can be overridden
|
60
|
+
# to handle the cases where the signature is not itself a valid C identifier (char*, for example)
|
61
|
+
def prefix = signature
|
62
|
+
|
63
|
+
def inspect = "#{signature} <#{self.class}>"
|
64
|
+
|
65
|
+
# Decorate identifier with type-specific prefix
|
66
|
+
def identifier(id, **kws) = (@decorator.nil? ? Composite.decorator : @decorator).(self, id, **kws)
|
67
|
+
|
68
|
+
def public? = @visibility == :public
|
69
|
+
|
70
|
+
def respond_to_missing?(meth, include_private = false) = @methods.has_key?(meth) ? true : super
|
71
|
+
|
72
|
+
def type_tag = signature
|
73
|
+
|
74
|
+
def defgroup = (public? ? :@public : :@internal).to_s + " @defgroup #{signature} #{type_tag}"
|
75
|
+
|
76
|
+
def ingroup = (public? ? :@public : :@internal).to_s + " @ingroup #{signature}"
|
77
|
+
|
78
|
+
def memory = (@allocator.nil? ? Composite.allocator : @allocator)
|
79
|
+
|
80
|
+
def hasher = (@hasher.nil? ? Composite.hasher : @hasher)
|
81
|
+
|
82
|
+
def self.decorator=(decorator) @decorator = decorator end
|
83
|
+
|
84
|
+
def self.decorator = @decorator
|
85
|
+
|
86
|
+
def self.allocator=(allocator) @allocator = allocator end
|
87
|
+
|
88
|
+
def self.allocator = @allocator
|
89
|
+
|
90
|
+
self.allocator = Allocator.instance # Standard C malloc() & free() memory handler
|
91
|
+
|
92
|
+
def self.hasher=(hasher) @hasher = hasher end
|
93
|
+
|
94
|
+
def self.hasher = @hasher
|
95
|
+
|
96
|
+
self.hasher = Hasher.instance # Default cycle-xor hasher
|
97
|
+
|
98
|
+
# Pluggable CamelCase identifier decorator
|
99
|
+
CAMEL_CASE_DECORATOR = -> (type, symbol, abbreviate: false, **kws) {
|
100
|
+
id = symbol.to_s.sub(/[!?]$/, '') # Strip trailing !?
|
101
|
+
_ = # Check for leading underscore
|
102
|
+
if /^(_+)(.*)/ =~ id
|
103
|
+
id = Regexp.last_match(2) # Chop leading underscore
|
104
|
+
true
|
105
|
+
else
|
106
|
+
false
|
107
|
+
end
|
108
|
+
id = id[0] if abbreviate
|
109
|
+
# Convert _separated_names to the CamelCase
|
110
|
+
id = type.prefix + id.split('_').collect{ |s| s[0].upcase << s[1..-1] }.join
|
111
|
+
# Carry over the method name's leading underscore only if the prefix is not in turn underscored
|
112
|
+
_ && !type.prefix.start_with?('_') ? Regexp.last_match(1) + id : id
|
113
|
+
}
|
114
|
+
|
115
|
+
# Pluggable _snake_case identifier decorator
|
116
|
+
SNAKE_CASE_DECORATOR = -> (type, symbol, abbreviate: false, **kws) {
|
117
|
+
id = symbol.to_s.sub(/[!?]$/, '') # Strip trailing !?
|
118
|
+
# Check for leading underscore
|
119
|
+
_ =
|
120
|
+
if /^(_+)(.*)/ =~ id
|
121
|
+
id = Regexp.last_match(2)
|
122
|
+
true
|
123
|
+
else
|
124
|
+
false
|
125
|
+
end
|
126
|
+
id = abbreviate ? "#{type.prefix}#{id[0]}" : "#{type.prefix}_#{id}"
|
127
|
+
# Carry over the method name's leading underscore only if the prefix is not in turn underscored
|
128
|
+
_ && !type.prefix.start_with?('_') ? Regexp.last_match(1) + id : id
|
129
|
+
}
|
130
|
+
|
131
|
+
self.decorator = CAMEL_CASE_DECORATOR
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def method_missing(meth, *args)
|
136
|
+
if (method = @methods[meth]).nil?
|
137
|
+
# On anything thats not a defined method return a type-decorated identifier
|
138
|
+
# This allows to generate arbitrary type-qualified identifiers with #{type.foo}
|
139
|
+
raise "unexpected arguments" unless args.empty?
|
140
|
+
identifier(meth)
|
141
|
+
else
|
142
|
+
method
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Overridable for custom method in derived classes
|
147
|
+
def method_class = Method
|
148
|
+
|
149
|
+
# Create a new type-bound function (aka method)
|
150
|
+
def method(result, name, parameters, inline: false, visibility: nil, constraint: true, instance: name, **kws)
|
151
|
+
method = method_class.new(
|
152
|
+
self,
|
153
|
+
result,
|
154
|
+
name,
|
155
|
+
parameters, # TODO force parameter types coercion
|
156
|
+
inline:,
|
157
|
+
visibility: (visibility.nil? ? self.visibility : visibility), # Method's visibility property can be borrowed from the type itself
|
158
|
+
constraint: constraint,
|
159
|
+
**kws
|
160
|
+
)
|
161
|
+
raise "##{instance} method redefinition is not allowed" if @methods.has_key?(instance)
|
162
|
+
@methods[instance] = method
|
163
|
+
references << method # Avoid introducing cyclic dependency due to the method's dependency on self
|
164
|
+
method
|
165
|
+
end
|
166
|
+
|
167
|
+
def configure
|
168
|
+
method(:void, :destroy, { target: lvalue }, constraint: -> { destructible? }).configure do
|
169
|
+
header %{
|
170
|
+
@brief Destroy existing value
|
171
|
+
|
172
|
+
@param[out] target value to be destroyed
|
173
|
+
|
174
|
+
This function destroys the value previously constructed with any constructor.
|
175
|
+
It involves freeing allocated memory and destroying the constituent values with the respective destructors.
|
176
|
+
|
177
|
+
It is an error to use the value after call to this function (`*target` is considered to contain garbage afterwards).
|
178
|
+
|
179
|
+
@since 2.0
|
180
|
+
}
|
181
|
+
end
|
182
|
+
method(:void, :create, { target: lvalue }, instance: :default_create, constraint: -> { default_constructible? }).configure do
|
183
|
+
header %{
|
184
|
+
@brief Create a new value
|
185
|
+
|
186
|
+
@param[out] target value to be created
|
187
|
+
|
188
|
+
This function constructs the value with parameterless constructor.
|
189
|
+
|
190
|
+
Previous contents of `*target` is overwritten.
|
191
|
+
|
192
|
+
Once constructed, the value is to be destroyed with @ref #{destroy}.
|
193
|
+
|
194
|
+
@since 2.0
|
195
|
+
}
|
196
|
+
end
|
197
|
+
method(:void, :copy, { target: lvalue, source: const_rvalue }, constraint: -> { copyable? }).configure do
|
198
|
+
header %{
|
199
|
+
@brief Create a copy of source value
|
200
|
+
|
201
|
+
@param[out] target value to be created
|
202
|
+
@param[in] source value to be cloned
|
203
|
+
|
204
|
+
This function is meant to an independent copy (a clone) of `*source` value in place of `*target`.
|
205
|
+
|
206
|
+
Previous contents of `*target` is overwritten.
|
207
|
+
|
208
|
+
Once constructed, the value is to be destroyed with @ref #{destroy}.
|
209
|
+
|
210
|
+
@since 2.0
|
211
|
+
}
|
212
|
+
end
|
213
|
+
method(:int, :equal, { left: const_rvalue, right: const_rvalue }, constraint: -> { comparable? }).configure do
|
214
|
+
header %{
|
215
|
+
@brief Perform equality testing of two values
|
216
|
+
|
217
|
+
@param[in] left value to test for equality
|
218
|
+
@param[in] right value to test for equality
|
219
|
+
|
220
|
+
@return non-zero if values are considered equal and zero otherwise
|
221
|
+
|
222
|
+
This function returns a non-zero value if specified values are considered equal and zero value otherwise.
|
223
|
+
Normally the values' contents are considered on equality testing.
|
224
|
+
|
225
|
+
@since 2.0
|
226
|
+
}
|
227
|
+
end
|
228
|
+
method(:int, :compare, { left: const_rvalue, right: const_rvalue }, constraint: -> { orderable? }).configure do
|
229
|
+
header %{
|
230
|
+
@brief Compute relative ordering of two values
|
231
|
+
|
232
|
+
@param[in] left value to order
|
233
|
+
@param[in] right value to order
|
234
|
+
|
235
|
+
@return negative, positive or zero value depending on comparison of the specified values
|
236
|
+
|
237
|
+
This function returns negative value if `left` precedes `right`, positive value if `left` follows `right` and zero if both values are considered equal.
|
238
|
+
|
239
|
+
Normally the values' contents are considered on comparison.
|
240
|
+
|
241
|
+
This function is in general independent to but is expected to be consistent with @ref #{equal} function.
|
242
|
+
|
243
|
+
@since 2.0
|
244
|
+
}
|
245
|
+
end
|
246
|
+
method(:size_t, :hash_code, { target: const_rvalue }, constraint: -> { hashable? } ).configure do
|
247
|
+
header %{
|
248
|
+
@brief Compute hash code
|
249
|
+
|
250
|
+
@param[in] target value to compute hash code for
|
251
|
+
|
252
|
+
@return hash code
|
253
|
+
|
254
|
+
This function computes a hash code which reflects the value's contents in some way,
|
255
|
+
that is two values considered equal must yield identical hash codes.
|
256
|
+
Two different values may or may not yield identical hash codes, however.
|
257
|
+
|
258
|
+
@since 2.0
|
259
|
+
}
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end # Composite
|
264
|
+
|
265
|
+
|
266
|
+
# Type-bound C side function
|
267
|
+
class Composite::Method < Function
|
268
|
+
|
269
|
+
attr_reader :type
|
270
|
+
|
271
|
+
def initialize(type, result, name, parameters, **kws)
|
272
|
+
@type = type
|
273
|
+
super(result.to_value, self.type.identifier(name), parameters, **kws)
|
274
|
+
dependencies << self.type << self.result.to_type
|
275
|
+
# TODO register parameters' types as dependencies
|
276
|
+
end
|
277
|
+
|
278
|
+
def method_missing(meth, *args)
|
279
|
+
if parameters.has_key?(meth) then parameters[meth]
|
280
|
+
elsif type.respond_to?(meth) then type.send(meth, *args)
|
281
|
+
else meth
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
private
|
286
|
+
|
287
|
+
def render_function_header(stream)
|
288
|
+
if public?
|
289
|
+
stream << %{
|
290
|
+
/**
|
291
|
+
#{type.ingroup}
|
292
|
+
#{@header}
|
293
|
+
*/
|
294
|
+
}
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def render_declaration_specifier(stream)
|
299
|
+
stream << (inline? ? 'AUTOC_INLINE ' : 'AUTOC_EXTERN ')
|
300
|
+
end
|
301
|
+
|
302
|
+
def render_implementation(stream)
|
303
|
+
render_function_definition(stream) if live? && !inline?
|
304
|
+
end
|
305
|
+
|
306
|
+
end # Method
|
307
|
+
|
308
|
+
|
309
|
+
Composite::DEFINITIONS = Code.new(
|
310
|
+
interface: %{
|
311
|
+
#ifndef AUTOC_INLINE
|
312
|
+
#if defined(__cplusplus)
|
313
|
+
#define AUTOC_INLINE inline
|
314
|
+
#elif defined(__clang__)
|
315
|
+
#define AUTOC_INLINE static __inline __attribute__((unused))
|
316
|
+
#elif __STDC_VERSION__ >= 199901L
|
317
|
+
#define AUTOC_INLINE static inline
|
318
|
+
#else
|
319
|
+
#define AUTOC_INLINE static __inline
|
320
|
+
#endif
|
321
|
+
#endif
|
322
|
+
#ifndef AUTOC_EXTERN
|
323
|
+
#ifdef __cplusplus
|
324
|
+
#define AUTOC_EXTERN extern "C"
|
325
|
+
#else
|
326
|
+
#define AUTOC_EXTERN extern
|
327
|
+
#endif
|
328
|
+
#endif
|
329
|
+
}
|
330
|
+
)
|
331
|
+
|
332
|
+
|
333
|
+
end
|