autoc 1.4 → 2.0.0
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.
- 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
|