rbs 3.4.3 → 3.5.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +7 -0
- data/CHANGELOG.md +0 -20
- data/Gemfile +12 -1
- data/Gemfile.lock +51 -34
- data/README.md +2 -1
- data/Rakefile +2 -2
- data/core/enumerator.rbs +1 -1
- data/core/gc.rbs +272 -150
- data/core/integer.rbs +4 -3
- data/core/io/wait.rbs +4 -4
- data/core/io.rbs +10 -3
- data/core/kernel.rbs +8 -7
- data/core/module.rbs +17 -4
- data/core/range.rbs +2 -2
- data/core/regexp.rbs +101 -90
- data/core/ruby_vm.rbs +103 -103
- data/core/string.rbs +3 -3
- data/core/symbol.rbs +2 -1
- data/core/thread.rbs +1 -1
- data/core/time.rbs +24 -4
- data/docs/architecture.md +110 -0
- data/docs/syntax.md +5 -1
- data/ext/rbs_extension/constants.c +2 -0
- data/ext/rbs_extension/constants.h +1 -0
- data/ext/rbs_extension/location.c +79 -70
- data/ext/rbs_extension/location.h +23 -5
- data/ext/rbs_extension/parser.c +82 -24
- data/ext/rbs_extension/parserstate.c +4 -0
- data/ext/rbs_extension/ruby_objs.c +13 -3
- data/ext/rbs_extension/ruby_objs.h +1 -0
- data/lib/rbs/collection/config.rb +1 -1
- data/lib/rbs/collection/sources/git.rb +1 -6
- data/lib/rbs/definition_builder/method_builder.rb +1 -1
- data/lib/rbs/definition_builder.rb +8 -8
- data/lib/rbs/diff.rb +1 -1
- data/lib/rbs/environment_loader.rb +2 -1
- data/lib/rbs/errors.rb +0 -14
- data/lib/rbs/parser_aux.rb +0 -5
- data/lib/rbs/prototype/helpers.rb +22 -12
- data/lib/rbs/prototype/rb.rb +38 -4
- data/lib/rbs/prototype/rbi.rb +30 -20
- data/lib/rbs/test/errors.rb +19 -14
- data/lib/rbs/test/tester.rb +1 -1
- data/lib/rbs/test/type_check.rb +95 -16
- data/lib/rbs/types.rb +112 -13
- data/lib/rbs/unit_test/spy.rb +1 -1
- data/lib/rbs/version.rb +1 -1
- data/rbs.gemspec +1 -1
- data/sig/environment_loader.rbs +1 -1
- data/sig/errors.rbs +1 -1
- data/sig/method_types.rbs +3 -3
- data/sig/prototype/helpers.rbs +4 -0
- data/sig/prototype/rbi.rbs +2 -0
- data/sig/types.rbs +54 -4
- data/sig/variance_calculator.rbs +2 -2
- data/stdlib/csv/0/csv.rbs +4 -1
- data/stdlib/fileutils/0/fileutils.rbs +1 -1
- data/stdlib/net-http/0/net-http.rbs +29 -27
- data/stdlib/socket/0/socket.rbs +2 -2
- data/stdlib/timeout/0/timeout.rbs +6 -0
- data/stdlib/uri/0/generic.rbs +2 -2
- data/stdlib/uri/0/http.rbs +2 -2
- metadata +3 -6
- data/lib/rbs/parser_compat/lexer_error.rb +0 -6
- data/lib/rbs/parser_compat/located_value.rb +0 -7
- data/lib/rbs/parser_compat/semantics_error.rb +0 -6
- data/lib/rbs/parser_compat/syntax_error.rb +0 -6
@@ -0,0 +1,110 @@
|
|
1
|
+
# Architecture
|
2
|
+
|
3
|
+
This guide describes the outline of the architecture of RBS library. It helps you to understand the structure and key features of the library to start contributing to the library.
|
4
|
+
|
5
|
+
## Bird's Eye View
|
6
|
+
|
7
|
+
The goal of the library is simple: Read RBS files and generate the structure of Ruby programs.
|
8
|
+
|
9
|
+
```
|
10
|
+
RBS files
|
11
|
+
↓ -- RBS::Parser
|
12
|
+
Syntax tree
|
13
|
+
↓
|
14
|
+
Environment
|
15
|
+
↓ -- Definition builder
|
16
|
+
Definition
|
17
|
+
```
|
18
|
+
|
19
|
+
The input is RBS files. The gem ships with RBS type definitions of Ruby core library and some of the standard libraries. You write RBS files for your applications or gems.
|
20
|
+
|
21
|
+
Syntax tree is the next representation. `RBS::Parser` transforms the sequence of characters in RBS files into syntax trees.
|
22
|
+
|
23
|
+
Syntax tree objects are loaded to `RBS::Environment`. It collects loaded RBS objects, organizes the definitions, and provides some utilities, like resolving type names and finding the declarations.
|
24
|
+
|
25
|
+
`RBS::Definition` is the goal of the transformation steps. It is associated with a class singleton, a class object, or an interface. You can find the list of available methods and their types, instance variables, and class hierarchies.
|
26
|
+
|
27
|
+
## Core classes
|
28
|
+
|
29
|
+
### Types
|
30
|
+
|
31
|
+
Types are defined under `RBS::Types`, like `RBS::Types::ClassInstance` or `RBS::Types::Union`. You will find the definition of each type supported in RBS.
|
32
|
+
|
33
|
+
### Parsing RBS files
|
34
|
+
|
35
|
+
The RBS source code is loaded into `RBS::Buffer`, and `RBS::Parser` is the parser. The parser is implemented in C extension.
|
36
|
+
|
37
|
+
`RBS::Parser` provides three entrypoints.
|
38
|
+
|
39
|
+
- `RBS::Parser.parse_method_type` parsers a *method type*. (`[T] (String) { (IO) -> T } -> Array[T]`)
|
40
|
+
- `RBS::Parser.parse_type` parses a *type*. (`Hash[Symbol, untyped]`)
|
41
|
+
- `RBS::Parser.parse_signature` parses the whole RBS file.
|
42
|
+
|
43
|
+
### Environment
|
44
|
+
|
45
|
+
RBS AST is loaded to `RBS::Environment` by `RBS::EnvironmentLoader`. `Environment` gives *absolute names* to the declarations, and provides an index from the *absolute name* to their declarations.
|
46
|
+
|
47
|
+
Assume we have the following nested RBS declarations:
|
48
|
+
|
49
|
+
```rbs
|
50
|
+
module Hello
|
51
|
+
class World
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Hello::World
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
And the environment organizes the definitions as follows:
|
60
|
+
|
61
|
+
- There are two classes `::Hello` and `::Hello::World`
|
62
|
+
- It provides a mapping from `::Hello` to it's `module` declaration and `::Hello::World` to it's two `class` declarations
|
63
|
+
|
64
|
+
### Definition and DefinitionBuilder
|
65
|
+
|
66
|
+
`RBS::Definition` tells you:
|
67
|
+
|
68
|
+
- The set of available methods in a class/module/interface
|
69
|
+
- The set of instance variables in a class/module
|
70
|
+
- The ancestors in a class/module
|
71
|
+
|
72
|
+
Definition is constructed for:
|
73
|
+
|
74
|
+
- A singleton class of a class/module -- `singleton(String)`, `singleton(Array)`,
|
75
|
+
- An instance of a class -- `String`, `Array[T]`, or
|
76
|
+
- An interface -- `_ToS`
|
77
|
+
|
78
|
+
Note that generic class instances/interfaces are kept generic. We don't have a definition of `Array[String]` but of `Array[T]`.
|
79
|
+
|
80
|
+
`DefinitionBuilder` constructs `Definition` of given type names.
|
81
|
+
|
82
|
+
- `DefinitionBuilder#build_singleton` returns a definition of singleton classes of given class/module.
|
83
|
+
- `DefinitionBuilder#build_instance` returns a definition of instances of given class/module.
|
84
|
+
- `DefinitionBuilder#build_interface` returns a definition of interfaces.
|
85
|
+
|
86
|
+
It uses `AncestorBuilder` to construct ancestor chains of the type. `MethodBuilder` constructs sets of available methods based on the ancestor chains.
|
87
|
+
|
88
|
+
The `#build_singleton` calculates the type of `.new` methods based on the definition of `#initialize` method. This is different from Ruby's implementation -- it reused `Class#new` method but we need the custom implementation to give precise `.new` method type of each class.
|
89
|
+
|
90
|
+
#### Working with type aliases
|
91
|
+
|
92
|
+
`DefinitionBuilder#expand_alias` and its variants provide one step *unfold* operation of type aliases.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
builder.expand_alias2(TypeName("::int"), []) # => returns `::Integer | ::_ToInt`
|
96
|
+
```
|
97
|
+
|
98
|
+
We don't have *normalize* operation for type aliases, because RBS allows recursive type alias definition, which cannot be *fully* unfolded.
|
99
|
+
|
100
|
+
### Other utilities
|
101
|
+
|
102
|
+
`RBS::Validator` provides validation of RBS type declaration. It validates that all of the type name references can be resolved, all type applications have correct arity, and so on.
|
103
|
+
|
104
|
+
`RBS::Test` provides runtime type checking, which confirms if a Ruby object can have an RBS type. It also provides an integration to existing Ruby code so that we run Ruby code, assuming unit tests, with runtime type checking.
|
105
|
+
|
106
|
+
`RBS::UnitTest` provides utilities to help write unit tests for RBS type definitions. Use the tool to make sure your RBS type definition is consistent with implementation.
|
107
|
+
|
108
|
+
`RBS::Prototype` is the core of `rbs prototype` feature. It scans Ruby source code or uses reflection features, and it generates the prototype of RBS files.
|
109
|
+
|
110
|
+
`RBS::Collection` includes `rbs collection` features.
|
data/docs/syntax.md
CHANGED
@@ -45,6 +45,7 @@ _literal_ ::= _string-literal_
|
|
45
45
|
| `false`
|
46
46
|
|
47
47
|
_proc_ ::= `^` _parameters?_ _self-type-binding?_ _block?_ `->` _type_
|
48
|
+
| `^` `(` `?` `)` `->` _type_ # Proc type with untyped parameter
|
48
49
|
```
|
49
50
|
|
50
51
|
### Class instance type
|
@@ -310,6 +311,7 @@ end
|
|
310
311
|
|
311
312
|
```markdown
|
312
313
|
_method-type_ ::= _parameters?_ _block?_ `->` _type_ # Method type
|
314
|
+
| `(` `?` `)` `->` _type_ # Method type with untyped parameters
|
313
315
|
|
314
316
|
_parameters?_ ::= (Empty)
|
315
317
|
| _parameters_ (Parameters)
|
@@ -333,9 +335,11 @@ _var-name_ ::= /[a-z]\w*/
|
|
333
335
|
_self-type-binding?_ = (Empty)
|
334
336
|
| `[` `self` `:` _type_ `]` (Self type binding)
|
335
337
|
|
336
|
-
_block?_ =
|
338
|
+
_block?_ = (No block)
|
337
339
|
| `{` _parameters_ _self-type-binding?_ `->` _type_ `}` (Block)
|
340
|
+
| `{` `(` `?` `)` `->` _type_ `}` (Block with untyped parameters)
|
338
341
|
| `?` `{` _parameters_ _self-type-binding?_ `->` _type_ `}` (Optional block)
|
342
|
+
| `?` `{` `(` `?` `)` `->` _type_ `}` (Optional block with untyped parameters)
|
339
343
|
```
|
340
344
|
|
341
345
|
### Parameters
|
@@ -61,6 +61,7 @@ VALUE RBS_Types_ClassInstance;
|
|
61
61
|
VALUE RBS_Types_ClassSingleton;
|
62
62
|
VALUE RBS_Types_Function_Param;
|
63
63
|
VALUE RBS_Types_Function;
|
64
|
+
VALUE RBS_Types_UntypedFunction;
|
64
65
|
VALUE RBS_Types_Interface;
|
65
66
|
VALUE RBS_Types_Intersection;
|
66
67
|
VALUE RBS_Types_Literal;
|
@@ -138,6 +139,7 @@ void rbs__init_constants(void) {
|
|
138
139
|
IMPORT_CONSTANT(RBS_Types_ClassInstance, RBS_Types, "ClassInstance");
|
139
140
|
IMPORT_CONSTANT(RBS_Types_ClassSingleton, RBS_Types, "ClassSingleton");
|
140
141
|
IMPORT_CONSTANT(RBS_Types_Function, RBS_Types, "Function");
|
142
|
+
IMPORT_CONSTANT(RBS_Types_UntypedFunction, RBS_Types, "UntypedFunction");
|
141
143
|
IMPORT_CONSTANT(RBS_Types_Function_Param, RBS_Types_Function, "Param");
|
142
144
|
IMPORT_CONSTANT(RBS_Types_Interface, RBS_Types, "Interface");
|
143
145
|
IMPORT_CONSTANT(RBS_Types_Intersection, RBS_Types, "Intersection");
|
@@ -64,6 +64,7 @@ extern VALUE RBS_Types_ClassInstance;
|
|
64
64
|
extern VALUE RBS_Types_ClassSingleton;
|
65
65
|
extern VALUE RBS_Types_Function_Param;
|
66
66
|
extern VALUE RBS_Types_Function;
|
67
|
+
extern VALUE RBS_Types_UntypedFunction;
|
67
68
|
extern VALUE RBS_Types_Interface;
|
68
69
|
extern VALUE RBS_Types_Intersection;
|
69
70
|
extern VALUE RBS_Types_Literal;
|
@@ -1,83 +1,76 @@
|
|
1
1
|
#include "rbs_extension.h"
|
2
2
|
|
3
|
+
#define RBS_LOC_REQUIRED_P(loc, i) ((loc)->children->required_p & (1 << (i)))
|
4
|
+
#define RBS_LOC_OPTIONAL_P(loc, i) (!RBS_LOC_REQUIRED_P((loc), (i)))
|
5
|
+
|
3
6
|
VALUE RBS_Location;
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
new->name = name;
|
9
|
-
new->rg = r;
|
10
|
-
return new;
|
8
|
+
position rbs_loc_position(int char_pos) {
|
9
|
+
position pos = { 0, char_pos, -1, -1 };
|
10
|
+
return pos;
|
11
11
|
}
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
} else {
|
17
|
-
return NULL;
|
18
|
-
}
|
13
|
+
position rbs_loc_position3(int char_pos, int line, int column) {
|
14
|
+
position pos = { 0, char_pos, line, column };
|
15
|
+
return pos;
|
19
16
|
}
|
20
17
|
|
21
|
-
void
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
list = next;
|
18
|
+
static void check_children_max(unsigned short n) {
|
19
|
+
size_t max = sizeof(rbs_loc_entry_bitmap) * 8;
|
20
|
+
if (n > max) {
|
21
|
+
rb_raise(rb_eRuntimeError, "Too many children added to location: %d", n);
|
26
22
|
}
|
27
23
|
}
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
if (list->name == name) {
|
32
|
-
*rg = list->rg;
|
33
|
-
return true;
|
34
|
-
}
|
25
|
+
void rbs_loc_alloc_children(rbs_loc *loc, unsigned short cap) {
|
26
|
+
check_children_max(cap);
|
35
27
|
|
36
|
-
|
37
|
-
|
28
|
+
size_t s = sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * cap;
|
29
|
+
loc->children = malloc(s);
|
38
30
|
|
39
|
-
|
31
|
+
loc->children->len = 0;
|
32
|
+
loc->children->required_p = 0;
|
33
|
+
loc->children->cap = cap;
|
40
34
|
}
|
41
35
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
static void check_children_cap(rbs_loc *loc) {
|
37
|
+
if (loc->children == NULL) {
|
38
|
+
rbs_loc_alloc_children(loc, 1);
|
39
|
+
} else {
|
40
|
+
if (loc->children->len == loc->children->cap) {
|
41
|
+
check_children_max(loc->children->cap + 1);
|
42
|
+
size_t s = sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * (++loc->children->cap);
|
43
|
+
loc->children = realloc(loc->children, s);
|
44
|
+
}
|
48
45
|
}
|
49
|
-
|
50
|
-
return size;
|
51
46
|
}
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
return pos;
|
56
|
-
}
|
48
|
+
void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r) {
|
49
|
+
check_children_cap(loc);
|
57
50
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
}
|
51
|
+
unsigned short i = loc->children->len++;
|
52
|
+
loc->children->entries[i].name = name;
|
53
|
+
loc->children->entries[i].rg = r;
|
62
54
|
|
63
|
-
|
64
|
-
loc->requireds = rbs_loc_list_add(loc->requireds, name, r);
|
55
|
+
loc->children->required_p |= 1 << i;
|
65
56
|
}
|
66
57
|
|
67
58
|
void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r) {
|
68
|
-
|
59
|
+
check_children_cap(loc);
|
60
|
+
|
61
|
+
unsigned short i = loc->children->len++;
|
62
|
+
loc->children->entries[i].name = name;
|
63
|
+
loc->children->entries[i].rg = r;
|
69
64
|
}
|
70
65
|
|
71
66
|
void rbs_loc_init(rbs_loc *loc, VALUE buffer, range rg) {
|
72
67
|
loc->buffer = buffer;
|
73
68
|
loc->rg = rg;
|
74
|
-
loc->
|
75
|
-
loc->requireds = NULL;
|
69
|
+
loc->children = NULL;
|
76
70
|
}
|
77
71
|
|
78
72
|
void rbs_loc_free(rbs_loc *loc) {
|
79
|
-
|
80
|
-
rbs_loc_list_free(loc->requireds);
|
73
|
+
free(loc->children);
|
81
74
|
ruby_xfree(loc);
|
82
75
|
}
|
83
76
|
|
@@ -89,7 +82,11 @@ static void rbs_loc_mark(void *ptr)
|
|
89
82
|
|
90
83
|
static size_t rbs_loc_memsize(const void *ptr) {
|
91
84
|
const rbs_loc *loc = ptr;
|
92
|
-
|
85
|
+
if (loc->children == NULL) {
|
86
|
+
return sizeof(rbs_loc);
|
87
|
+
} else {
|
88
|
+
return sizeof(rbs_loc) + sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * loc->children->cap;
|
89
|
+
}
|
93
90
|
}
|
94
91
|
|
95
92
|
static rb_data_type_t location_type = {
|
@@ -130,8 +127,10 @@ static VALUE location_initialize_copy(VALUE self, VALUE other) {
|
|
130
127
|
|
131
128
|
self_loc->buffer = other_loc->buffer;
|
132
129
|
self_loc->rg = other_loc->rg;
|
133
|
-
|
134
|
-
|
130
|
+
if (other_loc->children != NULL) {
|
131
|
+
rbs_loc_alloc_children(self_loc, other_loc->children->cap);
|
132
|
+
memcpy(self_loc->children, other_loc->children, sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * other_loc->children->cap);
|
133
|
+
}
|
135
134
|
|
136
135
|
return Qnil;
|
137
136
|
}
|
@@ -221,18 +220,19 @@ VALUE rbs_new_location(VALUE buffer, range rg) {
|
|
221
220
|
static VALUE location_aref(VALUE self, VALUE name) {
|
222
221
|
rbs_loc *loc = rbs_check_location(self);
|
223
222
|
|
224
|
-
range result;
|
225
223
|
ID id = SYM2ID(name);
|
226
224
|
|
227
|
-
if (
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
225
|
+
if (loc->children != NULL) {
|
226
|
+
for (unsigned short i = 0; i < loc->children->len; i++) {
|
227
|
+
if (loc->children->entries[i].name == id) {
|
228
|
+
range result = loc->children->entries[i].rg;
|
229
|
+
|
230
|
+
if (RBS_LOC_OPTIONAL_P(loc, i) && null_range_p(result)) {
|
231
|
+
return Qnil;
|
232
|
+
} else {
|
233
|
+
return rbs_new_location(loc->buffer, result);
|
234
|
+
}
|
235
|
+
}
|
236
236
|
}
|
237
237
|
}
|
238
238
|
|
@@ -244,11 +244,16 @@ static VALUE location_optional_keys(VALUE self) {
|
|
244
244
|
VALUE keys = rb_ary_new();
|
245
245
|
|
246
246
|
rbs_loc *loc = rbs_check_location(self);
|
247
|
-
|
247
|
+
rbs_loc_children *children = loc->children;
|
248
|
+
if (children == NULL) {
|
249
|
+
return keys;
|
250
|
+
}
|
248
251
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
+
for (unsigned short i = 0; i < children->len; i++) {
|
253
|
+
if (RBS_LOC_OPTIONAL_P(loc, i)) {
|
254
|
+
rb_ary_push(keys, ID2SYM(children->entries[i].name));
|
255
|
+
|
256
|
+
}
|
252
257
|
}
|
253
258
|
|
254
259
|
return keys;
|
@@ -258,11 +263,15 @@ static VALUE location_required_keys(VALUE self) {
|
|
258
263
|
VALUE keys = rb_ary_new();
|
259
264
|
|
260
265
|
rbs_loc *loc = rbs_check_location(self);
|
261
|
-
|
266
|
+
rbs_loc_children *children = loc->children;
|
267
|
+
if (children == NULL) {
|
268
|
+
return keys;
|
269
|
+
}
|
262
270
|
|
263
|
-
|
264
|
-
|
265
|
-
|
271
|
+
for (unsigned short i = 0; i < children->len; i++) {
|
272
|
+
if (RBS_LOC_REQUIRED_P(loc, i)) {
|
273
|
+
rb_ary_push(keys, ID2SYM(children->entries[i].name));
|
274
|
+
}
|
266
275
|
}
|
267
276
|
|
268
277
|
return keys;
|
@@ -9,17 +9,24 @@
|
|
9
9
|
* */
|
10
10
|
extern VALUE RBS_Location;
|
11
11
|
|
12
|
-
typedef struct
|
12
|
+
typedef struct {
|
13
13
|
ID name;
|
14
14
|
range rg;
|
15
|
-
|
16
|
-
|
15
|
+
} rbs_loc_entry;
|
16
|
+
|
17
|
+
typedef unsigned int rbs_loc_entry_bitmap;
|
18
|
+
|
19
|
+
typedef struct {
|
20
|
+
unsigned short len;
|
21
|
+
unsigned short cap;
|
22
|
+
rbs_loc_entry_bitmap required_p;
|
23
|
+
rbs_loc_entry entries[0];
|
24
|
+
} rbs_loc_children;
|
17
25
|
|
18
26
|
typedef struct {
|
19
27
|
VALUE buffer;
|
20
28
|
range rg;
|
21
|
-
|
22
|
-
rbs_loc_list *optionals;
|
29
|
+
rbs_loc_children *children;
|
23
30
|
} rbs_loc;
|
24
31
|
|
25
32
|
/**
|
@@ -32,13 +39,24 @@ VALUE rbs_new_location(VALUE buffer, range rg);
|
|
32
39
|
* */
|
33
40
|
rbs_loc *rbs_check_location(VALUE location);
|
34
41
|
|
42
|
+
/**
|
43
|
+
* Allocate memory for child locations.
|
44
|
+
*
|
45
|
+
* Do not call twice for the same location.
|
46
|
+
* */
|
47
|
+
void rbs_loc_alloc_children(rbs_loc *loc, unsigned short cap);
|
48
|
+
|
35
49
|
/**
|
36
50
|
* Add a required child range with given name.
|
51
|
+
*
|
52
|
+
* Allocate memory for children with rbs_loc_alloc_children before calling this function.
|
37
53
|
* */
|
38
54
|
void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r);
|
39
55
|
|
40
56
|
/**
|
41
57
|
* Add an optional child range with given name.
|
58
|
+
*
|
59
|
+
* Allocate memory for children with rbs_loc_alloc_children before calling this function.
|
42
60
|
* */
|
43
61
|
void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r);
|
44
62
|
|