diff options
-rw-r--r-- | lib/prism/parse_result.rb | 26 | ||||
-rw-r--r-- | prism/extension.c | 13 | ||||
-rw-r--r-- | prism/prettyprint.h | 15 | ||||
-rw-r--r-- | prism/prism.h | 14 | ||||
-rw-r--r-- | prism/templates/lib/prism/node.rb.erb | 8 | ||||
-rw-r--r-- | prism/templates/src/prettyprint.c.erb | 134 | ||||
-rw-r--r-- | prism/util/pm_buffer.c | 21 | ||||
-rw-r--r-- | prism/util/pm_buffer.h | 3 | ||||
-rw-r--r-- | prism/util/pm_constant_pool.c | 2 | ||||
-rw-r--r-- | prism/util/pm_constant_pool.h | 2 | ||||
-rw-r--r-- | prism/util/pm_newline_list.c | 62 | ||||
-rw-r--r-- | prism/util/pm_newline_list.h | 2 |
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); |