Skip to content

Commit 9f12a56

Browse files
committed
Expose flags on every node type
1 parent 4cc0eda commit 9f12a56

32 files changed

+252
-305
lines changed

config.yml

Lines changed: 37 additions & 111 deletions
Large diffs are not rendered by default.

docs/serialization.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ Each node is structured like the following table:
117117
| --- | --- |
118118
| `1` | node type |
119119
| location | node location |
120+
| varuint | node flags |
120121

121122
Every field on the node is then appended to the serialized string. The fields can be determined by referencing `config.yml`. Depending on the type of field, it could take a couple of different forms, described below:
122123

lib/prism/node_ext.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ module RegularExpressionOptions # :nodoc:
2121
# Returns a numeric value that represents the flags that were used to create
2222
# the regular expression.
2323
def options
24-
o = flags & (RegularExpressionFlags::IGNORE_CASE | RegularExpressionFlags::EXTENDED | RegularExpressionFlags::MULTI_LINE)
24+
o = 0
25+
o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
26+
o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED)
27+
o |= Regexp::MULTILINE if flags.anybits?(RegularExpressionFlags::MULTI_LINE)
2528
o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
2629
o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
2730
o
@@ -87,6 +90,7 @@ def to_interpolated
8790
InterpolatedXStringNode.new(
8891
source,
8992
location,
93+
flags,
9094
opening_loc,
9195
[StringNode.new(source, content_loc, 0, nil, content_loc, nil, unescaped)],
9296
closing_loc
@@ -117,7 +121,7 @@ def numeric
117121
if denominator == 1
118122
IntegerNode.new(source, location.chop, flags, numerator)
119123
else
120-
FloatNode.new(source, location.chop, numerator.to_f / denominator)
124+
FloatNode.new(source, location.chop, 0, numerator.to_f / denominator)
121125
end
122126
end
123127
end
@@ -195,7 +199,7 @@ def full_name
195199
# continue to supply that API.
196200
def child
197201
deprecated("name", "name_loc")
198-
name ? ConstantReadNode.new(source, name_loc, name) : MissingNode.new(source, location)
202+
name ? ConstantReadNode.new(source, name_loc, 0, name) : MissingNode.new(source, location, 0)
199203
end
200204
end
201205

@@ -231,7 +235,7 @@ def full_name
231235
# continue to supply that API.
232236
def child
233237
deprecated("name", "name_loc")
234-
name ? ConstantReadNode.new(source, name_loc, name) : MissingNode.new(source, location)
238+
name ? ConstantReadNode.new(source, name_loc, 0, name) : MissingNode.new(source, location, 0)
235239
end
236240
end
237241

lib/prism/parse_result/newlines.rb

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def visit_block_node(node)
4545

4646
# Mark if/unless nodes as newlines.
4747
def visit_if_node(node)
48-
node.newline!(@lines)
48+
node.newline_flag!(@lines)
4949
super(node)
5050
end
5151

@@ -54,101 +54,101 @@ def visit_if_node(node)
5454
# Permit statements lists to mark newlines within themselves.
5555
def visit_statements_node(node)
5656
node.body.each do |child|
57-
child.newline!(@lines)
57+
child.newline_flag!(@lines)
5858
end
5959
super(node)
6060
end
6161
end
6262
end
6363

6464
class Node
65-
def newline? # :nodoc:
66-
@newline ? true : false
65+
def newline_flag? # :nodoc:
66+
@newline_flag ? true : false
6767
end
6868

69-
def newline!(lines) # :nodoc:
69+
def newline_flag!(lines) # :nodoc:
7070
line = location.start_line
7171
unless lines[line]
7272
lines[line] = true
73-
@newline = true
73+
@newline_flag = true
7474
end
7575
end
7676
end
7777

7878
class BeginNode < Node
79-
def newline!(lines) # :nodoc:
79+
def newline_flag!(lines) # :nodoc:
8080
# Never mark BeginNode with a newline flag, mark children instead.
8181
end
8282
end
8383

8484
class ParenthesesNode < Node
85-
def newline!(lines) # :nodoc:
85+
def newline_flag!(lines) # :nodoc:
8686
# Never mark ParenthesesNode with a newline flag, mark children instead.
8787
end
8888
end
8989

9090
class IfNode < Node
91-
def newline!(lines) # :nodoc:
92-
predicate.newline!(lines)
91+
def newline_flag!(lines) # :nodoc:
92+
predicate.newline_flag!(lines)
9393
end
9494
end
9595

9696
class UnlessNode < Node
97-
def newline!(lines) # :nodoc:
98-
predicate.newline!(lines)
97+
def newline_flag!(lines) # :nodoc:
98+
predicate.newline_flag!(lines)
9999
end
100100
end
101101

102102
class UntilNode < Node
103-
def newline!(lines) # :nodoc:
104-
predicate.newline!(lines)
103+
def newline_flag!(lines) # :nodoc:
104+
predicate.newline_flag!(lines)
105105
end
106106
end
107107

108108
class WhileNode < Node
109-
def newline!(lines) # :nodoc:
110-
predicate.newline!(lines)
109+
def newline_flag!(lines) # :nodoc:
110+
predicate.newline_flag!(lines)
111111
end
112112
end
113113

114114
class RescueModifierNode < Node
115-
def newline!(lines) # :nodoc:
116-
expression.newline!(lines)
115+
def newline_flag!(lines) # :nodoc:
116+
expression.newline_flag!(lines)
117117
end
118118
end
119119

120120
class InterpolatedMatchLastLineNode < Node
121-
def newline!(lines) # :nodoc:
121+
def newline_flag!(lines) # :nodoc:
122122
first = parts.first
123-
first.newline!(lines) if first
123+
first.newline_flag!(lines) if first
124124
end
125125
end
126126

127127
class InterpolatedRegularExpressionNode < Node
128-
def newline!(lines) # :nodoc:
128+
def newline_flag!(lines) # :nodoc:
129129
first = parts.first
130-
first.newline!(lines) if first
130+
first.newline_flag!(lines) if first
131131
end
132132
end
133133

134134
class InterpolatedStringNode < Node
135-
def newline!(lines) # :nodoc:
135+
def newline_flag!(lines) # :nodoc:
136136
first = parts.first
137-
first.newline!(lines) if first
137+
first.newline_flag!(lines) if first
138138
end
139139
end
140140

141141
class InterpolatedSymbolNode < Node
142-
def newline!(lines) # :nodoc:
142+
def newline_flag!(lines) # :nodoc:
143143
first = parts.first
144-
first.newline!(lines) if first
144+
first.newline_flag!(lines) if first
145145
end
146146
end
147147

148148
class InterpolatedXStringNode < Node
149-
def newline!(lines) # :nodoc:
149+
def newline_flag!(lines) # :nodoc:
150150
first = parts.first
151-
first.newline!(lines) if first
151+
first.newline_flag!(lines) if first
152152
end
153153
end
154154
end

sig/prism/_private/node.rbs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module Prism
22
class Node
3-
@newline: bool
3+
@newline_flag: bool
44

5-
def newline?: () -> bool
6-
def set_newline_flag: (Array[bool]) -> void
5+
def newline_flag?: () -> bool
6+
def newline_flag!: (Array[bool] lines) -> void
77
end
88
end

templates/ext/prism/api_node.c.erb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,20 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
170170
<%- nodes.each do |node| -%>
171171
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
172172
case <%= node.type %>: {
173-
<%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::FlagsField].include?(field.class) } -%>
173+
<%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField].include?(field.class) } -%>
174174
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
175175
<%- end -%>
176-
VALUE argv[<%= node.fields.length + 2 %>];
176+
VALUE argv[<%= node.fields.length + 3 %>];
177177

178178
// source
179179
argv[0] = source;
180180

181181
// location
182182
argv[1] = pm_location_new(parser, node->location.start, node->location.end);
183-
<%- node.fields.each.with_index(2) do |field, index| -%>
183+
184+
// flags
185+
argv[2] = ULONG2NUM(node->flags);
186+
<%- node.fields.each.with_index(3) do |field, index| -%>
184187

185188
// <%= field.name %>
186189
<%- case field -%>
@@ -221,9 +224,6 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
221224
<%- when Prism::Template::UInt32Field -%>
222225
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
223226
argv[<%= index %>] = ULONG2NUM(cast-><%= field.name %>);
224-
<%- when Prism::Template::FlagsField -%>
225-
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
226-
argv[<%= index %>] = ULONG2NUM(node->flags & ~PM_NODE_FLAG_COMMON_MASK);
227227
<%- when Prism::Template::IntegerField -%>
228228
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
229229
argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>);
@@ -235,7 +235,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
235235
<%- end -%>
236236
<%- end -%>
237237

238-
rb_ary_push(value_stack, rb_class_new_instance(<%= node.fields.length + 2 %>, argv, rb_cPrism<%= node.name %>));
238+
rb_ary_push(value_stack, rb_class_new_instance(<%= node.fields.length + 3 %>, argv, rb_cPrism<%= node.name %>));
239239
break;
240240
}
241241
<%- end -%>

templates/include/prism/ast.h.erb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,8 @@ typedef uint16_t pm_node_flags_t;
100100
* We store the flags enum in every node in the tree. Some flags are common to
101101
* all nodes (the ones listed below). Others are specific to certain node types.
102102
*/
103-
#define PM_NODE_FLAG_BITS (sizeof(pm_node_flags_t) * 8)
104-
105-
static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = (1 << (PM_NODE_FLAG_BITS - 1));
106-
static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = (1 << (PM_NODE_FLAG_BITS - 2));
107-
static const pm_node_flags_t PM_NODE_FLAG_COMMON_MASK = (1 << (PM_NODE_FLAG_BITS - 1)) | (1 << (PM_NODE_FLAG_BITS - 2));
103+
static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = 0x1;
104+
static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2;
108105

109106
/**
110107
* Cast the type to an enum to allow the compiler to provide exhaustiveness
@@ -151,11 +148,10 @@ typedef struct pm_node {
151148
* <%= node.name %>
152149
*
153150
* Type: <%= node.type %>
154-
<%- if (node_flags = node.fields.find { |field| field.is_a? Prism::Template::FlagsField }) -%>
151+
<%- if (node_flags = node.flags) -%>
155152
* Flags:
156-
<%- found = flags.find { |flag| flag.name == node_flags.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%>
157-
<%- found.values.each do |value| -%>
158-
* PM_<%= found.human.upcase %>_<%= value.name %>
153+
<%- node_flags.values.each do |value| -%>
154+
* PM_<%= node_flags.human.upcase %>_<%= value.name %>
159155
<%- end -%>
160156
<%- end -%>
161157
*
@@ -164,7 +160,7 @@ typedef struct pm_node {
164160
typedef struct pm_<%= node.human %> {
165161
/** The embedded base node. */
166162
pm_node_t base;
167-
<%- node.fields.grep_v(Prism::Template::FlagsField).each do |field| -%>
163+
<%- node.fields.each do |field| -%>
168164

169165
/**
170166
* <%= node.name %>#<%= field.name %>
@@ -201,7 +197,7 @@ typedef enum pm_<%= flag.human %> {
201197
<%- flag.values.each_with_index do |value, index| -%>
202198
<%= "\n" if index > 0 -%>
203199
/** <%= value.comment %> */
204-
PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << index %>,
200+
PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << (index + 2) %>,
205201
<%- end -%>
206202
} pm_<%= flag.human %>_t;
207203
<%- end -%>

templates/java/org/prism/Loader.java.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ public class Loader {
362362
case <%= index + 1 %>:
363363
<%-
364364
params = node.needs_serialized_length? ? ["buffer.getInt()"] : []
365+
params << "loadFlags()"
365366
params.concat node.semantic_fields.map { |field|
366367
case field
367368
when Prism::Template::NodeField then "#{field.java_cast}loadNode()"
@@ -378,7 +379,6 @@ public class Loader {
378379
when Prism::Template::OptionalLocationField then "loadOptionalLocation()"
379380
when Prism::Template::UInt8Field then "buffer.get()"
380381
when Prism::Template::UInt32Field then "loadVarUInt()"
381-
when Prism::Template::FlagsField then "loadFlags()"
382382
when Prism::Template::IntegerField then "loadInteger()"
383383
when Prism::Template::DoubleField then "buffer.getDouble()"
384384
else raise

templates/java/org/prism/Nodes.java.erb

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,25 +220,28 @@ public abstract class Nodes {
220220
<%- end -%>
221221

222222
<%-
223-
params = node.needs_serialized_length? ? ["int serializedLength"] : []
223+
params = []
224+
params << "int serializedLength" if node.needs_serialized_length?
225+
params << "short flags"
224226
params.concat node.semantic_fields.map { |field| "#{field.java_type} #{field.name}" }
225227
params.concat ["int startOffset", "int length"]
226228
-%>
227-
public <%=node.name -%>(<%= params.join(", ") %>) {
229+
public <%= node.name -%>(<%= params.join(", ") %>) {
228230
super(startOffset, length);
229231
<%- if node.needs_serialized_length? -%>
230232
this.serializedLength = serializedLength;
231233
<%- end -%>
234+
this.flags = flags;
232235
<%- node.semantic_fields.each do |field| -%>
233236
this.<%= field.name %> = <%= field.name %>;
234237
<%- end -%>
235238
}
236239
<%# methods for flags -%>
237-
<%- node.semantic_fields.grep(Prism::Template::FlagsField).each do |field| -%>
238-
<%- flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag }.values.each do |value| -%>
240+
<%- if (node_flags = node.flags) -%>
241+
<%- node_flags.values.each do |value| -%>
239242

240243
public boolean is<%= value.camelcase %>() {
241-
return <%= field.kind %>.is<%= value.camelcase %>(this.<%= field.name %>);
244+
return <%= node_flags.name %>.is<%= value.camelcase %>(this.<%= node_flags.name %>);
242245
}
243246
<%- end -%>
244247
<%- end -%>
@@ -321,7 +324,7 @@ public abstract class Nodes {
321324
<%- if node.fields.any?(Prism::Template::NodeListField) or node.fields.any?(Prism::Template::ConstantListField) -%>
322325
String nextNextIndent = nextIndent + " ";
323326
<%- end -%>
324-
<%- node.fields.grep_v(Prism::Template::LocationField).grep_v(Prism::Template::OptionalLocationField).each do |field| -%>
327+
<%- [*node.flags, *node.fields.grep_v(Prism::Template::LocationField).grep_v(Prism::Template::OptionalLocationField)].each do |field| -%>
325328
builder.append(nextIndent);
326329
builder.append("<%= field.name %>: ");
327330
<%- case field -%>
@@ -348,7 +351,10 @@ public abstract class Nodes {
348351
for (<%= string_type %> constant : this.<%= field.name %>) {
349352
builder.append(nextNextIndent).append('"').append(constant).append('"').append('\n');
350353
}
351-
<%- when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::IntegerField, Prism::Template::DoubleField -%>
354+
<%- when Prism::Template::Flags -%>
355+
builder.append(this.flags);
356+
builder.append('\n');
357+
<%- when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField, Prism::Template::DoubleField -%>
352358
builder.append(this.<%= field.name %>);
353359
builder.append('\n');
354360
<%- else -%>

templates/javascript/src/deserialize.js.erb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ export function deserialize(source, array) {
303303
<%- if node.needs_serialized_length? -%>
304304
buffer.readUint32();
305305
<%- end -%>
306-
return new nodes.<%= node.name %>(<%= (node.fields.map { |field|
306+
return new nodes.<%= node.name %>(<%= ["location", "buffer.readVarInt()", *node.fields.map { |field|
307307
case field
308308
when Prism::Template::NodeField then "readRequiredNode()"
309309
when Prism::Template::OptionalNodeField then "readOptionalNode()"
@@ -315,12 +315,11 @@ export function deserialize(source, array) {
315315
when Prism::Template::LocationField then "buffer.readLocation()"
316316
when Prism::Template::OptionalLocationField then "buffer.readOptionalLocation()"
317317
when Prism::Template::UInt8Field then "buffer.readByte()"
318-
when Prism::Template::UInt32Field, Prism::Template::FlagsField then "buffer.readVarInt()"
318+
when Prism::Template::UInt32Field then "buffer.readVarInt()"
319319
when Prism::Template::IntegerField then "readInteger()"
320320
when Prism::Template::DoubleField then "buffer.readDouble()"
321-
else raise
322321
end
323-
} + ["location"]).join(", ") -%>);
322+
}].join(", ") -%>);
324323
<%- end -%>
325324
default:
326325
throw new Error(`Unknown node type: ${type}`);

0 commit comments

Comments
 (0)