summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/prism/parse_result.rb26
-rw-r--r--prism/extension.c13
-rw-r--r--prism/prettyprint.h15
-rw-r--r--prism/prism.h14
-rw-r--r--prism/templates/lib/prism/node.rb.erb8
-rw-r--r--prism/templates/src/prettyprint.c.erb134
-rw-r--r--prism/util/pm_buffer.c21
-rw-r--r--prism/util/pm_buffer.h3
-rw-r--r--prism/util/pm_constant_pool.c2
-rw-r--r--prism/util/pm_constant_pool.h2
-rw-r--r--prism/util/pm_newline_list.c62
-rw-r--r--prism/util/pm_newline_list.h2
12 files changed, 173 insertions, 129 deletions
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index fd2737b20c..00ae3aaa1a 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -16,16 +16,32 @@ module Prism
source.byteslice(offset, length)
end
+ # Binary search through the offsets to find the line number for the given
+ # offset.
def line(value)
- offsets.bsearch_index { |offset| offset > value } || offsets.length
+ left = 0
+ right = offsets.length - 1
+
+ while left <= right
+ mid = left + (right - left) / 2
+ return mid if offsets[mid] == value
+
+ if offsets[mid] < value
+ left = mid + 1
+ else
+ right = mid - 1
+ end
+ end
+
+ left - 1
end
def line_offset(value)
- offsets[line(value) - 1]
+ offsets[line(value)]
end
def column(value)
- value - offsets[line(value) - 1]
+ value - offsets[line(value)]
end
private
@@ -86,7 +102,7 @@ module Prism
# The line number where this location starts.
def start_line
- source.line(start_offset)
+ source.line(start_offset) + 1
end
# The content of the line where this location starts before this location.
@@ -97,7 +113,7 @@ module Prism
# The line number where this location ends.
def end_line
- source.line(end_offset - 1)
+ source.line(end_offset) + 1
end
# The column number in bytes where this location starts from the start of
diff --git a/prism/extension.c b/prism/extension.c
index 755876e561..786adb2c0f 100644
--- a/prism/extension.c
+++ b/prism/extension.c
@@ -554,8 +554,10 @@ parse_serialize_file_metadata(VALUE self, VALUE filepath, VALUE metadata) {
return result;
}
+// Inspect the AST that represents the given source using the prism pretty print
+// as opposed to the Ruby implementation.
static VALUE
-rb_prism_debug_inspect_node(VALUE self, VALUE source) {
+inspect_node(VALUE self, VALUE source) {
pm_string_t input;
input_load_string(&input, source);
@@ -565,8 +567,10 @@ rb_prism_debug_inspect_node(VALUE self, VALUE source) {
pm_node_t *node = pm_parse(&parser);
pm_buffer_t buffer = { 0 };
- pm_prettyprint(&parser, node, &buffer);
- VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer));
+ pm_prettyprint(&buffer, &parser, node);
+
+ rb_encoding *encoding = rb_enc_find(parser.encoding.name);
+ VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
pm_buffer_free(&buffer);
pm_node_destroy(&parser, node);
@@ -627,8 +631,7 @@ Init_prism(void) {
rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1);
rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
rb_define_singleton_method(rb_cPrismDebug, "parse_serialize_file_metadata", parse_serialize_file_metadata, 2);
-
- rb_define_singleton_method(rb_cPrismDebug, "inspect_node", rb_prism_debug_inspect_node, 1);
+ rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1);
// Next, initialize the other APIs.
Init_prism_api_node();
diff --git a/prism/prettyprint.h b/prism/prettyprint.h
new file mode 100644
index 0000000000..04596793d4
--- /dev/null
+++ b/prism/prettyprint.h
@@ -0,0 +1,15 @@
+#ifndef PRISM_PRETTYPRINT_H
+#define PRISM_PRETTYPRINT_H
+
+#include "prism/defines.h"
+
+#include <stdio.h>
+
+#include "prism/ast.h"
+#include "prism/parser.h"
+#include "prism/util/pm_buffer.h"
+
+// Pretty-prints the AST represented by the given node to the given buffer.
+PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node);
+
+#endif
diff --git a/prism/prism.h b/prism/prism.h
index 25ac08f68b..99a6a7e2eb 100644
--- a/prism/prism.h
+++ b/prism/prism.h
@@ -2,16 +2,17 @@
#define PRISM_H
#include "prism/defines.h"
+#include "prism/util/pm_buffer.h"
+#include "prism/util/pm_char.h"
+#include "prism/util/pm_memchr.h"
+#include "prism/util/pm_strpbrk.h"
#include "prism/ast.h"
#include "prism/diagnostic.h"
#include "prism/node.h"
#include "prism/pack.h"
#include "prism/parser.h"
+#include "prism/prettyprint.h"
#include "prism/regexp.h"
-#include "prism/util/pm_buffer.h"
-#include "prism/util/pm_char.h"
-#include "prism/util/pm_memchr.h"
-#include "prism/util/pm_strpbrk.h"
#include "prism/version.h"
#include <assert.h>
@@ -29,8 +30,6 @@
void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
-void pm_print_node(pm_parser_t *parser, pm_node_t *node);
-
void pm_parser_metadata(pm_parser_t *parser, const char *metadata);
// The prism version and the serialization format.
@@ -56,9 +55,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
// Parse the Ruby source associated with the given parser and return the tree.
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser);
-// Pretty-prints the AST represented by the given node to the given buffer.
-PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
-
// Serialize the AST represented by the given node to the given buffer.
PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb
index f083e318e0..47ae6850a0 100644
--- a/prism/templates/lib/prism/node.rb.erb
+++ b/prism/templates/lib/prism/node.rb.erb
@@ -179,8 +179,14 @@ module Prism
inspector << "<%= pointer %><%= field.name %>:\n"
inspector << <%= field.name %>.inspect(inspector.child_inspector("<%= preadd %>")).delete_prefix(inspector.prefix)
end
- <%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::StringField, Prism::UInt32Field -%>
+ <%- when Prism::ConstantField, Prism::StringField, Prism::UInt32Field -%>
inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
+ <%- when Prism::OptionalConstantField -%>
+ if (<%= field.name %> = self.<%= field.name %>).nil?
+ inspector << "<%= pointer %><%= field.name %>: ∅\n"
+ else
+ inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n"
+ end
<%- when Prism::FlagsField -%>
<%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise unless flag } -%>
flags = [<%= flag.values.map { |value| "(\"#{value.name.downcase}\" if #{value.name.downcase}?)" }.join(", ") %>].compact
diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb
index 99405f3761..43d7c57190 100644
--- a/prism/templates/src/prettyprint.c.erb
+++ b/prism/templates/src/prettyprint.c.erb
@@ -7,27 +7,67 @@
#include "prism/util/pm_buffer.h"
static void
-prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *node, pm_buffer_t *prefix_buffer);
+prettyprint_source(pm_buffer_t *output_buffer, const uint8_t *source, size_t length) {
+ for (size_t index = 0; index < length; index++) {
+ const uint8_t byte = source[index];
-static void
-prettyprint_location(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_location_t *location) {
- char printed[] = "[0000-0000]";
- snprintf(printed, sizeof(printed), "[%04ld-%04ld]", (long int) (location->start - parser->start), (long int) (location->end - parser->start));
- pm_buffer_append_string(output_buffer, printed, strlen(printed));
+ if ((byte <= 0x06) || (byte >= 0x0E && byte <= 0x1F) || (byte >= 0x7F)) {
+ pm_buffer_append_format(output_buffer, "\\x%02X", byte);
+ } else {
+ switch (byte) {
+ case '\a': pm_buffer_append_string(output_buffer, "\\a", 2); break;
+ case '\b': pm_buffer_append_string(output_buffer, "\\b", 2); break;
+ case '\t': pm_buffer_append_string(output_buffer, "\\t", 2); break;
+ case '\n': pm_buffer_append_string(output_buffer, "\\n", 2); break;
+ case '\v': pm_buffer_append_string(output_buffer, "\\v", 2); break;
+ case '\f': pm_buffer_append_string(output_buffer, "\\f", 2); break;
+ case '\r': pm_buffer_append_string(output_buffer, "\\r", 2); break;
+ case '"': pm_buffer_append_string(output_buffer, "\\\"", 2); break;
+ case '#': {
+ if (index + 1 < length) {
+ const uint8_t next_byte = source[index + 1];
+ if (next_byte == '{' || next_byte == '@' || next_byte == '$') {
+ pm_buffer_append_byte(output_buffer, '\\');
+ }
+ }
+
+ pm_buffer_append_byte(output_buffer, '#');
+ break;
+ }
+ case '\\': pm_buffer_append_string(output_buffer, "\\\\", 2); break;
+ default: pm_buffer_append_byte(output_buffer, byte); break;
+ }
+ }
+ }
+}
+
+static inline void
+prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) {
+ pm_line_column_t start = pm_newline_list_line_column(&parser->newline_list, location->start);
+ pm_line_column_t end = pm_newline_list_line_column(&parser->newline_list, location->end);
+ pm_buffer_append_format(output_buffer, "(%d,%d)-(%d,%d)", start.line + 1, start.column, end.line + 1, end.column);
+}
+
+static inline void
+prettyprint_constant(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_constant_id_t constant_id) {
+ pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
+ pm_buffer_append_format(output_buffer, ":%.*s", (int) constant->length, constant->start);
}
static void
-prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *node, pm_buffer_t *prefix_buffer) {
+prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, const pm_node_t *node, pm_buffer_t *prefix_buffer) {
switch (PM_NODE_TYPE(node)) {
case PM_SCOPE_NODE:
// We do not need to print a ScopeNode as it's not part of the AST.
return;
<%- nodes.each do |node| -%>
case <%= node.type %>: {
- <%- if node.fields.any? { |field| !field.is_a?(Prism::FlagsField) } -%>
+ <%- if node.fields.any? -%>
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
<%- end -%>
- pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ()-())\n", <%= node.name.length + 21 %>);
+ pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ", <%= node.name.length + 14 %>);
+ prettyprint_location(output_buffer, parser, &node->location);
+ pm_buffer_append_string(output_buffer, ")\n", 2);
<%- node.fields.each_with_index do |field, index| -%>
<%- pointer, preadd = index == node.fields.length - 1 ? ["└── ", " "] : ["├── ", "│ "] -%>
@@ -58,17 +98,18 @@ prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *nod
}
<%- when Prism::StringField -%>
pm_buffer_append_string(output_buffer, " \"", 2);
- pm_buffer_append_bytes(output_buffer, pm_string_source(&cast-><%= field.name %>), pm_string_length(&cast-><%= field.name %>));
+ prettyprint_source(output_buffer, pm_string_source(&cast-><%= field.name %>), pm_string_length(&cast-><%= field.name %>));
pm_buffer_append_string(output_buffer, "\"\n", 2);
<%- when Prism::NodeListField -%>
- pm_buffer_append_string(output_buffer, " (length: )\n", 13);
- size_t last_index = cast-><%= field.name %>.size - 1;
- for (uint32_t index = 0; index <= last_index; index++) {
+ pm_buffer_append_format(output_buffer, " (length: %d)\n", cast-><%= field.name %>.size);
+
+ size_t last_index = cast-><%= field.name %>.size;
+ for (uint32_t index = 0; index < last_index; index++) {
size_t prefix_length = prefix_buffer->length;
- pm_buffer_append_string(prefix_buffer, " ", 4);
+ pm_buffer_append_string(prefix_buffer, "<%= preadd %>", <%= preadd.bytesize %>);
pm_buffer_concat(output_buffer, prefix_buffer);
- if (index == last_index) {
+ if (index == last_index - 1) {
pm_buffer_append_string(output_buffer, "└── ", 10);
pm_buffer_append_string(prefix_buffer, " ", 4);
} else {
@@ -79,55 +120,56 @@ prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *nod
prettyprint_node(output_buffer, parser, (pm_node_t *) cast-><%= field.name %>.nodes[index], prefix_buffer);
prefix_buffer->length = prefix_length;
}
- pm_buffer_append_string(output_buffer, "\n", 1);
<%- when Prism::ConstantField -%>
- char <%= field.name %>_buffer[12];
- snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "%u", cast-><%= field.name %>);
pm_buffer_append_byte(output_buffer, ' ');
- pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
+ prettyprint_constant(output_buffer, parser, cast-><%= field.name %>);
pm_buffer_append_byte(output_buffer, '\n');
<%- when Prism::OptionalConstantField -%>
if (cast-><%= field.name %> == 0) {
pm_buffer_append_string(output_buffer, " ∅\n", 5);
} else {
- char <%= field.name %>_buffer[12];
- snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "%u", cast-><%= field.name %>);
pm_buffer_append_byte(output_buffer, ' ');
- pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
+ prettyprint_constant(output_buffer, parser, cast-><%= field.name %>);
pm_buffer_append_byte(output_buffer, '\n');
}
<%- when Prism::ConstantListField -%>
pm_buffer_append_string(output_buffer, " [", 2);
for (uint32_t index = 0; index < cast-><%= field.name %>.size; index++) {
if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2);
- char <%= field.name %>_buffer[12];
- snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "%u", cast-><%= field.name %>.ids[index]);
- pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
+ prettyprint_constant(output_buffer, parser, cast-><%= field.name %>.ids[index]);
}
pm_buffer_append_string(output_buffer, "]\n", 2);
<%- when Prism::LocationField -%>
+ pm_location_t *location = &cast-><%= field.name %>;
pm_buffer_append_byte(output_buffer, ' ');
- prettyprint_location(output_buffer, parser, &cast-><%= field.name %>);
- pm_buffer_append_byte(output_buffer, '\n');
+ prettyprint_location(output_buffer, parser, location);
+ pm_buffer_append_string(output_buffer, " = \"", 4);
+ prettyprint_source(output_buffer, location->start, (size_t) (location->end - location->start));
+ pm_buffer_append_string(output_buffer, "\"\n", 2);
<%- when Prism::OptionalLocationField -%>
- if (cast-><%= field.name %>.start == NULL) {
+ pm_location_t *location = &cast-><%= field.name %>;
+ if (location->start == NULL) {
pm_buffer_append_string(output_buffer, " ∅\n", 5);
} else {
pm_buffer_append_byte(output_buffer, ' ');
- prettyprint_location(output_buffer, parser, &cast-><%= field.name %>);
- pm_buffer_append_byte(output_buffer, '\n');
+ prettyprint_location(output_buffer, parser, location);
+ pm_buffer_append_string(output_buffer, " = \"", 4);
+ prettyprint_source(output_buffer, location->start, (size_t) (location->end - location->start));
+ pm_buffer_append_string(output_buffer, "\"\n", 2);
}
<%- when Prism::UInt32Field -%>
- char <%= field.name %>_buffer[12];
- snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "+%d", cast-><%= field.name %>);
- pm_buffer_append_byte(output_buffer, ' ');
- pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
- pm_buffer_append_byte(output_buffer, '\n');
+ pm_buffer_append_format(output_buffer, " %d\n", cast-><%= field.name %>);
<%- when Prism::FlagsField -%>
- char <%= field.name %>_buffer[12];
- snprintf(<%= field.name %>_buffer, sizeof(<%= field.name %>_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK));
- pm_buffer_append_byte(output_buffer, ' ');
- pm_buffer_append_string(output_buffer, <%= field.name %>_buffer, strlen(<%= field.name %>_buffer));
+ bool found = false;
+ <%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%>
+ <%- found.values.each do |value| -%>
+ if (cast->base.<%= field.name %> & PM_<%= found.human.upcase %>_<%= value.name %>) {
+ if (found) pm_buffer_append_byte(output_buffer, ',');
+ pm_buffer_append_string(output_buffer, " <%= value.name.downcase %>", <%= value.name.bytesize + 1 %>);
+ found = true;
+ }
+ <%- end -%>
+ if (!found) pm_buffer_append_string(output_buffer, " ∅", 4);
pm_buffer_append_byte(output_buffer, '\n');
<%- else -%>
<%- raise -%>
@@ -141,21 +183,9 @@ prettyprint_node(pm_buffer_t *output_buffer, pm_parser_t *parser, pm_node_t *nod
}
}
-void
-pm_print_node(pm_parser_t *parser, pm_node_t *node) {
- pm_buffer_t output_buffer = { 0 };
- pm_buffer_t prefix_buffer = { 0 };
-
- prettyprint_node(&output_buffer, parser, node, &prefix_buffer);
- printf("%.*s\n", (int) output_buffer.length, output_buffer.value);
-
- pm_buffer_free(&output_buffer);
- pm_buffer_free(&prefix_buffer);
-}
-
// Pretty-prints the AST represented by the given node to the given buffer.
PRISM_EXPORTED_FUNCTION void
-pm_prettyprint(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *output_buffer) {
+pm_prettyprint(pm_buffer_t *output_buffer, pm_parser_t *parser, const pm_node_t *node) {
pm_buffer_t prefix_buffer = { 0 };
prettyprint_node(output_buffer, parser, node, &prefix_buffer);
pm_buffer_free(&prefix_buffer);
diff --git a/prism/util/pm_buffer.c b/prism/util/pm_buffer.c
index 9547df203a..db2415a807 100644
--- a/prism/util/pm_buffer.c
+++ b/prism/util/pm_buffer.c
@@ -70,6 +70,27 @@ pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length) {
memset(buffer->value + cursor, 0, length);
}
+// Append a formatted string to the buffer.
+void
+pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ int result = vsnprintf(NULL, 0, format, arguments);
+ va_end(arguments);
+
+ if (result < 0) return;
+ size_t length = (size_t) (result + 1);
+
+ size_t cursor = buffer->length;
+ pm_buffer_append_length(buffer, length);
+
+ va_start(arguments, format);
+ vsnprintf(buffer->value + cursor, length, format, arguments);
+ va_end(arguments);
+
+ buffer->length--;
+}
+
// Append a string to the buffer.
void
pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length) {
diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h
index 82a468e4db..b8b7c41a10 100644
--- a/prism/util/pm_buffer.h
+++ b/prism/util/pm_buffer.h
@@ -36,6 +36,9 @@ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(pm_buffer_t *buffer);
// Append the given amount of space as zeroes to the buffer.
void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length);
+// Append a formatted string to the buffer.
+void pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...);
+
// Append a string to the buffer.
void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length);
diff --git a/prism/util/pm_constant_pool.c b/prism/util/pm_constant_pool.c
index 8ed97c86a3..7d76f8370e 100644
--- a/prism/util/pm_constant_pool.c
+++ b/prism/util/pm_constant_pool.c
@@ -156,7 +156,7 @@ pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity) {
// Return a pointer to the constant indicated by the given constant id.
pm_constant_t *
-pm_constant_pool_id_to_constant(pm_constant_pool_t *pool, pm_constant_id_t constant_id) {
+pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id) {
assert(constant_id > 0 && constant_id <= pool->size);
return &pool->constants[constant_id - 1];
}
diff --git a/prism/util/pm_constant_pool.h b/prism/util/pm_constant_pool.h
index defd6ad27d..fa9081f737 100644
--- a/prism/util/pm_constant_pool.h
+++ b/prism/util/pm_constant_pool.h
@@ -76,7 +76,7 @@ typedef struct {
bool pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity);
// Return a pointer to the constant indicated by the given constant id.
-pm_constant_t * pm_constant_pool_id_to_constant(pm_constant_pool_t *pool, pm_constant_id_t constant_id);
+pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id);
// Insert a constant into a constant pool that is a slice of a source string.
// Returns the id of the constant, or 0 if any potential calls to resize fail.
diff --git a/prism/util/pm_newline_list.c b/prism/util/pm_newline_list.c
index 779a0a8d5c..20a1a221cb 100644
--- a/prism/util/pm_newline_list.c
+++ b/prism/util/pm_newline_list.c
@@ -53,10 +53,14 @@ pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor) {
return pm_newline_list_append(list, cursor);
}
-// Returns the line and column of the given offset, assuming we don't have any
-// information about the previous index that we found.
-static pm_line_column_t
-pm_newline_list_line_column_search(pm_newline_list_t *list, size_t offset) {
+// Returns the line and column of the given offset. If the offset is not in the
+// list, the line and column of the closest offset less than the given offset
+// are returned.
+pm_line_column_t
+pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor) {
+ assert(cursor >= list->start);
+ size_t offset = (size_t) (cursor - list->start);
+
size_t left = 0;
size_t right = list->size - 1;
@@ -77,56 +81,6 @@ pm_newline_list_line_column_search(pm_newline_list_t *list, size_t offset) {
return ((pm_line_column_t) { left - 1, offset - list->offsets[left - 1] });
}
-// Returns the line and column of the given offset, assuming we know the last
-// index that we found.
-static pm_line_column_t
-pm_newline_list_line_column_scan(pm_newline_list_t *list, size_t offset) {
- if (offset > list->last_offset) {
- size_t index = list->last_index;
- while (index < list->size && list->offsets[index] < offset) {
- index++;
- }
-
- if (index == list->size) {
- return ((pm_line_column_t) { index - 1, offset - list->offsets[index - 1] });
- }
-
- return ((pm_line_column_t) { index, 0 });
- } else {
- size_t index = list->last_index;
- while (index > 0 && list->offsets[index] > offset) {
- index--;
- }
-
- if (index == 0) {
- return ((pm_line_column_t) { 0, offset });
- }
-
- return ((pm_line_column_t) { index, offset - list->offsets[index - 1] });
- }
-}
-
-// Returns the line and column of the given offset. If the offset is not in the
-// list, the line and column of the closest offset less than the given offset
-// are returned.
-pm_line_column_t
-pm_newline_list_line_column(pm_newline_list_t *list, const uint8_t *cursor) {
- assert(cursor >= list->start);
- size_t offset = (size_t) (cursor - list->start);
- pm_line_column_t result;
-
- if (list->last_offset == 0) {
- result = pm_newline_list_line_column_search(list, offset);
- } else {
- result = pm_newline_list_line_column_scan(list, offset);
- }
-
- list->last_index = result.line;
- list->last_offset = offset;
-
- return result;
-}
-
// Free the internal memory allocated for the newline list.
void
pm_newline_list_free(pm_newline_list_t *list) {
diff --git a/prism/util/pm_newline_list.h b/prism/util/pm_newline_list.h
index 38fb40196d..da6c565d6b 100644
--- a/prism/util/pm_newline_list.h
+++ b/prism/util/pm_newline_list.h
@@ -53,7 +53,7 @@ bool pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor
// Returns the line and column of the given offset. If the offset is not in the
// list, the line and column of the closest offset less than the given offset
// are returned.
-pm_line_column_t pm_newline_list_line_column(pm_newline_list_t *list, const uint8_t *cursor);
+pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor);
// Free the internal memory allocated for the newline list.
void pm_newline_list_free(pm_newline_list_t *list);