Skip to content

Commit 04d329d

Browse files
committed
Introduce a BlockLocalVariableNode
This is a tradeoff that I think is worth it. Right now we have a location list that tracks the location of each of the block locals. Instead, I'd like to make that a node list that has a proper node in each spot in the list. In doing so, we eliminate the need to have a location list at all, making it simpler on all of the various consumers as we have one fewer field type. There should be minimal memory implications here since this syntax is exceedingly rare.
1 parent 38c20cf commit 04d329d

29 files changed

+78
-176
lines changed

bin/memsize

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ results =
1616
8
1717
when "location", "location?"
1818
16
19-
when "node[]", "string", "token", "token?", "location[]", "constant[]"
19+
when "node[]", "string", "token", "token?", "constant[]"
2020
24
2121
when "flags"
2222
0

config.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,15 @@ nodes:
520520
521521
bar(&args)
522522
^^^^^^^^^^
523+
- name: BlockLocalVariableNode
524+
fields:
525+
- name: name
526+
type: constant
527+
comment: |
528+
Represents a block local variable.
529+
530+
a { |; b| }
531+
^
523532
- name: BlockNode
524533
fields:
525534
- name: locals
@@ -556,7 +565,7 @@ nodes:
556565
type: node?
557566
kind: ParametersNode
558567
- name: locals
559-
type: location[]
568+
type: node[]
560569
- name: opening_loc
561570
type: location?
562571
- name: closing_loc

docs/configuration.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ The available values for `type` are:
5151
* `constant[]` - A child node that is an array of constants. This is a `yp_constant_id_list_t` in C.
5252
* `location` - A child node that is a location. This is a `yp_location_t` in C.
5353
* `location?` - A child node that is a location that is optionally present. This is a `yp_location_t` in C, but if the value is not present then the `start` and `end` fields will be `NULL`.
54-
* `location[]` - A child node that is an array of locations. This is a `yp_location_list_t` in C.
5554
* `uint32` - A child node that is a 32-bit unsigned integer. This is a `uint32_t` in C.
5655

5756
If the type is `node` or `node?` then the value also accepts an optional `kind` key (a string). This key is expected to match to the name of another node type within `config.yml`. This changes a couple of places where code is templated out to use the more specific struct name instead of the generic `yp_node_t`. For example, with `kind: StatementsNode` the `yp_node_t *` in C becomes a `yp_statements_node_t *`.

docs/serialization.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ Depending on the type of child node, it could take a couple of different forms,
9393
* `constant[]` - A child node that is an array of constants. This is structured as a variable-length integer length, followed by the child constants themselves.
9494
* `location` - A child node that is a location. This is structured as a variable-length integer start followed by a variable-length integer length.
9595
* `location?` - A child node that is a location that is optionally present. If the location is not present, then a single `0` byte will be written in its place. If it is present, then it will be structured just like the `location` child node.
96-
* `location[]` - A child node that is an array of locations. This is structured as a `4` byte length, followed by the locations themselves.
9796
* `uint32` - A child node that is a 32-bit unsigned integer. This is structured as a variable-length integer.
9897

9998
After the syntax tree, the content pool is serialized.

include/yarp/node.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
#include "yarp/defines.h"
55
#include "yarp/parser.h"
66

7-
// Append a token to the given list.
8-
void yp_location_list_append(yp_location_list_t *list, const yp_token_t *token);
9-
107
// Append a new node onto the end of the node list.
118
void yp_node_list_append(yp_node_list_t *list, yp_node_t *node);
129

@@ -31,7 +28,6 @@ YP_EXPORTED_FUNCTION void yp_node_memsize(yp_node_t *node, yp_memsize_t *memsize
3128
YP_EXPORTED_FUNCTION const char * yp_node_type_to_str(yp_node_type_t node_type);
3229

3330
#define YP_EMPTY_NODE_LIST ((yp_node_list_t) { .nodes = NULL, .size = 0, .capacity = 0 })
34-
#define YP_EMPTY_LOCATION_LIST ((yp_location_list_t) { .locations = NULL, .size = 0, .capacity = 0 })
3531

3632
#endif // YARP_NODE_H
3733

rust/yarp/build.rs

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ enum NodeFieldType {
3434
#[serde(rename = "location?")]
3535
OptionalLocation,
3636

37-
#[serde(rename = "location[]")]
38-
LocationList,
39-
4037
#[serde(rename = "uint32")]
4138
UInt32,
4239

@@ -254,12 +251,6 @@ fn write_node(file: &mut File, node: &Node) -> Result<(), Box<dyn std::error::Er
254251
writeln!(file, " }}")?;
255252
writeln!(file, " }}")?;
256253
},
257-
NodeFieldType::LocationList => {
258-
writeln!(file, " pub fn {}(&self) -> LocationList<'pr> {{", field.name)?;
259-
writeln!(file, " let pointer: *mut yp_location_list_t = unsafe {{ &mut (*self.pointer).{} }};", field.name)?;
260-
writeln!(file, " LocationList {{ pointer: unsafe {{ NonNull::new_unchecked(pointer) }}, marker: PhantomData }}")?;
261-
writeln!(file, " }}")?;
262-
},
263254
NodeFieldType::UInt32 => {
264255
writeln!(file, " pub fn {}(&self) -> u32 {{", field.name)?;
265256
writeln!(file, " unsafe {{ (*self.pointer).{} }}", field.name)?;
@@ -454,51 +445,6 @@ impl std::fmt::Debug for Location<'_> {{
454445
}}
455446
}}
456447
457-
/// An iterator over the ranges in a list.
458-
pub struct LocationListIter<'pr> {{
459-
pointer: NonNull<yp_location_list_t>,
460-
index: usize,
461-
marker: PhantomData<&'pr mut yp_location_list_t>
462-
}}
463-
464-
impl<'pr> Iterator for LocationListIter<'pr> {{
465-
type Item = Location<'pr>;
466-
467-
fn next(&mut self) -> Option<Self::Item> {{
468-
if self.index >= unsafe {{ self.pointer.as_ref().size }} {{
469-
None
470-
}} else {{
471-
let pointer: *mut yp_location_t = unsafe {{ self.pointer.as_ref().locations.add(self.index) }};
472-
self.index += 1;
473-
Some(Location {{ pointer: unsafe {{ NonNull::new_unchecked(pointer) }}, marker: PhantomData }})
474-
}}
475-
}}
476-
}}
477-
478-
/// A list of ranges in the source file.
479-
pub struct LocationList<'pr> {{
480-
pointer: NonNull<yp_location_list_t>,
481-
marker: PhantomData<&'pr mut yp_location_list_t>
482-
}}
483-
484-
impl<'pr> LocationList<'pr> {{
485-
/// Returns an iterator over the locations.
486-
#[must_use]
487-
pub fn iter(&self) -> LocationListIter<'pr> {{
488-
LocationListIter {{
489-
pointer: self.pointer,
490-
index: 0,
491-
marker: PhantomData
492-
}}
493-
}}
494-
}}
495-
496-
impl std::fmt::Debug for LocationList<'_> {{
497-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{
498-
write!(f, "{{:?}}", self.iter().collect::<Vec<_>>())
499-
}}
500-
}}
501-
502448
/// An iterator over the nodes in a list.
503449
pub struct NodeListIter<'pr> {{
504450
parser: NonNull<yp_parser_t>,

rust/yarp/src/lib.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -262,29 +262,6 @@ mod tests {
262262
assert_eq!(slice, "222");
263263
}
264264

265-
#[test]
266-
fn location_list_test() {
267-
use super::{
268-
Visit,
269-
visit_block_parameters_node, BlockParametersNode
270-
};
271-
272-
struct BlockLocalsVisitor {}
273-
274-
impl Visit<'_> for BlockLocalsVisitor {
275-
fn visit_block_parameters_node(&mut self, node: &BlockParametersNode<'_>) {
276-
println!("{:?}", node.locals());
277-
visit_block_parameters_node(self, node);
278-
}
279-
}
280-
281-
let source = "-> (; foo, bar) {}";
282-
let result = parse(source.as_ref());
283-
284-
let mut visitor = BlockLocalsVisitor {};
285-
visitor.visit(&result.node());
286-
}
287-
288265
#[test]
289266
fn visitor_test() {
290267
use super::{

src/yarp.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,7 @@ yp_block_parameters_node_create(yp_parser_t *parser, yp_parameters_node_t *param
11751175
.parameters = parameters,
11761176
.opening_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
11771177
.closing_loc = { .start = NULL, .end = NULL },
1178-
.locals = YP_EMPTY_LOCATION_LIST
1178+
.locals = YP_EMPTY_NODE_LIST
11791179
};
11801180

11811181
return node;
@@ -1190,14 +1190,30 @@ yp_block_parameters_node_closing_set(yp_block_parameters_node_t *node, const yp_
11901190
node->closing_loc = YP_LOCATION_TOKEN_VALUE(closing);
11911191
}
11921192

1193+
// Allocate and initialize a new BlockLocalVariableNode node.
1194+
static yp_block_local_variable_node_t *
1195+
yp_block_local_variable_node_create(yp_parser_t *parser, const yp_token_t *name) {
1196+
assert(name->type == YP_TOKEN_IDENTIFIER || name->type == YP_TOKEN_MISSING);
1197+
yp_block_local_variable_node_t *node = YP_ALLOC_NODE(parser, yp_block_local_variable_node_t);
1198+
1199+
*node = (yp_block_local_variable_node_t) {
1200+
{
1201+
.type = YP_NODE_BLOCK_LOCAL_VARIABLE_NODE,
1202+
.location = YP_LOCATION_TOKEN_VALUE(name),
1203+
},
1204+
.name = yp_parser_constant_id_token(parser, name)
1205+
};
1206+
1207+
return node;
1208+
}
1209+
11931210
// Append a new block-local variable to a BlockParametersNode node.
11941211
static void
1195-
yp_block_parameters_node_append_local(yp_block_parameters_node_t *node, const yp_token_t *local) {
1196-
assert(local->type == YP_TOKEN_IDENTIFIER || local->type == YP_TOKEN_MISSING);
1212+
yp_block_parameters_node_append_local(yp_block_parameters_node_t *node, const yp_block_local_variable_node_t *local) {
1213+
yp_node_list_append(&node->locals, (yp_node_t *) local);
11971214

1198-
yp_location_list_append(&node->locals, local);
1199-
if (node->base.location.start == NULL) node->base.location.start = local->start;
1200-
node->base.location.end = local->end;
1215+
if (node->base.location.start == NULL) node->base.location.start = local->base.location.start;
1216+
node->base.location.end = local->base.location.end;
12011217
}
12021218

12031219
// Allocate and initialize a new BreakNode node.
@@ -9283,7 +9299,9 @@ parse_block_parameters(
92839299
do {
92849300
expect(parser, YP_TOKEN_IDENTIFIER, "Expected a local variable name.");
92859301
yp_parser_local_add_token(parser, &parser->previous);
9286-
yp_block_parameters_node_append_local(block_parameters, &parser->previous);
9302+
9303+
yp_block_local_variable_node_t *local = yp_block_local_variable_node_create(parser, &parser->previous);
9304+
yp_block_parameters_node_append_local(block_parameters, local);
92879305
} while (accept(parser, YP_TOKEN_COMMA));
92889306
}
92899307

templates/ext/yarp/api_node.c.erb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,6 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) {
152152
}
153153
<%- when YARP::StringField -%>
154154
argv[<%= index %>] = yp_string_new(&cast-><%= field.name %>, encoding);
155-
<%- when YARP::LocationListField -%>
156-
argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
157-
for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
158-
yp_location_t location = cast-><%= field.name %>.locations[index];
159-
rb_ary_push(argv[<%= index %>], yp_location_new(parser, location.start, location.end, source));
160-
}
161155
<%- when YARP::ConstantField -%>
162156
argv[<%= index %>] = rb_id2sym(constants[cast-><%= field.name %> - 1]);
163157
<%- when YARP::ConstantListField -%>

templates/include/yarp/ast.h.erb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@ typedef struct {
3232
const uint8_t *end;
3333
} yp_location_t;
3434

35-
typedef struct {
36-
yp_location_t *locations;
37-
size_t size;
38-
size_t capacity;
39-
} yp_location_list_t;
40-
4135
struct yp_node;
4236

4337
typedef struct yp_node_list {
@@ -95,7 +89,6 @@ typedef struct yp_<%= node.human %> {
9589
<%= case field
9690
when YARP::NodeField, YARP::OptionalNodeField then "struct #{field.c_type} *#{field.name}"
9791
when YARP::NodeListField then "struct yp_node_list #{field.name}"
98-
when YARP::LocationListField then "yp_location_list_t #{field.name}"
9992
when YARP::ConstantField then "yp_constant_id_t #{field.name}"
10093
when YARP::ConstantListField then "yp_constant_id_list_t #{field.name}"
10194
when YARP::StringField then "yp_string_t #{field.name}"

0 commit comments

Comments
 (0)