diff --git a/src/main/c/yarp/Makefile b/src/main/c/yarp/Makefile index 8e1c4b20d475..dd08ce3b6163 100644 --- a/src/main/c/yarp/Makefile +++ b/src/main/c/yarp/Makefile @@ -13,6 +13,7 @@ SOEXT := $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]') CPPFLAGS := -Iinclude CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -fPIC -fvisibility=hidden CC := cc +WASI_SDK_PATH := /opt/wasi-sdk HEADERS := $(shell find include -name '*.h') SOURCES := $(shell find src -name '*.c') @@ -23,6 +24,7 @@ all: shared static shared: build/librubyparser.$(SOEXT) static: build/librubyparser.a +wasm: javascript/src/prism.wasm build/librubyparser.$(SOEXT): $(SHARED_OBJECTS) $(ECHO) "linking $@" @@ -32,6 +34,10 @@ build/librubyparser.a: $(STATIC_OBJECTS) $(ECHO) "building $@" $(Q) $(AR) $(ARFLAGS) $@ $(STATIC_OBJECTS) $(Q1:0=>/dev/null) +javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) + $(ECHO) "building $@" + $(Q) $(WASI_SDK_PATH)/bin/clang --sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot/ $(DEBUG_FLAGS) -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -o $@ $(SOURCES) + build/shared/%.o: src/%.c Makefile $(HEADERS) $(ECHO) "compiling $@" $(Q) mkdir -p $(@D) diff --git a/src/main/c/yarp/include/prism.h b/src/main/c/yarp/include/prism.h index c06e0fd2787b..99a6a7e2eb72 100644 --- a/src/main/c/yarp/include/prism.h +++ b/src/main/c/yarp/include/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 @@ -29,13 +30,8 @@ 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); -// Generate a scope node from the given node. -void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser); - // The prism version and the serialization format. PRISM_EXPORTED_FUNCTION const char * pm_version(void); @@ -59,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/src/main/c/yarp/include/prism/ast.h b/src/main/c/yarp/include/prism/ast.h index 401c9bab630c..093811e62ff0 100644 --- a/src/main/c/yarp/include/prism/ast.h +++ b/src/main/c/yarp/include/prism/ast.h @@ -277,79 +277,81 @@ enum pm_node_type { PM_IMAGINARY_NODE = 66, PM_IMPLICIT_NODE = 67, PM_IN_NODE = 68, - PM_INSTANCE_VARIABLE_AND_WRITE_NODE = 69, - PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE = 70, - PM_INSTANCE_VARIABLE_OR_WRITE_NODE = 71, - PM_INSTANCE_VARIABLE_READ_NODE = 72, - PM_INSTANCE_VARIABLE_TARGET_NODE = 73, - PM_INSTANCE_VARIABLE_WRITE_NODE = 74, - PM_INTEGER_NODE = 75, - PM_INTERPOLATED_MATCH_LAST_LINE_NODE = 76, - PM_INTERPOLATED_REGULAR_EXPRESSION_NODE = 77, - PM_INTERPOLATED_STRING_NODE = 78, - PM_INTERPOLATED_SYMBOL_NODE = 79, - PM_INTERPOLATED_X_STRING_NODE = 80, - PM_KEYWORD_HASH_NODE = 81, - PM_KEYWORD_PARAMETER_NODE = 82, - PM_KEYWORD_REST_PARAMETER_NODE = 83, - PM_LAMBDA_NODE = 84, - PM_LOCAL_VARIABLE_AND_WRITE_NODE = 85, - PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE = 86, - PM_LOCAL_VARIABLE_OR_WRITE_NODE = 87, - PM_LOCAL_VARIABLE_READ_NODE = 88, - PM_LOCAL_VARIABLE_TARGET_NODE = 89, - PM_LOCAL_VARIABLE_WRITE_NODE = 90, - PM_MATCH_LAST_LINE_NODE = 91, - PM_MATCH_PREDICATE_NODE = 92, - PM_MATCH_REQUIRED_NODE = 93, - PM_MATCH_WRITE_NODE = 94, - PM_MISSING_NODE = 95, - PM_MODULE_NODE = 96, - PM_MULTI_TARGET_NODE = 97, - PM_MULTI_WRITE_NODE = 98, - PM_NEXT_NODE = 99, - PM_NIL_NODE = 100, - PM_NO_KEYWORDS_PARAMETER_NODE = 101, - PM_NUMBERED_REFERENCE_READ_NODE = 102, - PM_OPTIONAL_PARAMETER_NODE = 103, - PM_OR_NODE = 104, - PM_PARAMETERS_NODE = 105, - PM_PARENTHESES_NODE = 106, - PM_PINNED_EXPRESSION_NODE = 107, - PM_PINNED_VARIABLE_NODE = 108, - PM_POST_EXECUTION_NODE = 109, - PM_PRE_EXECUTION_NODE = 110, - PM_PROGRAM_NODE = 111, - PM_RANGE_NODE = 112, - PM_RATIONAL_NODE = 113, - PM_REDO_NODE = 114, - PM_REGULAR_EXPRESSION_NODE = 115, - PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE = 116, - PM_REQUIRED_PARAMETER_NODE = 117, - PM_RESCUE_MODIFIER_NODE = 118, - PM_RESCUE_NODE = 119, - PM_REST_PARAMETER_NODE = 120, - PM_RETRY_NODE = 121, - PM_RETURN_NODE = 122, - PM_SELF_NODE = 123, - PM_SINGLETON_CLASS_NODE = 124, - PM_SOURCE_ENCODING_NODE = 125, - PM_SOURCE_FILE_NODE = 126, - PM_SOURCE_LINE_NODE = 127, - PM_SPLAT_NODE = 128, - PM_STATEMENTS_NODE = 129, - PM_STRING_CONCAT_NODE = 130, - PM_STRING_NODE = 131, - PM_SUPER_NODE = 132, - PM_SYMBOL_NODE = 133, - PM_TRUE_NODE = 134, - PM_UNDEF_NODE = 135, - PM_UNLESS_NODE = 136, - PM_UNTIL_NODE = 137, - PM_WHEN_NODE = 138, - PM_WHILE_NODE = 139, - PM_X_STRING_NODE = 140, - PM_YIELD_NODE = 141, + PM_INDEX_AND_WRITE_NODE = 69, + PM_INDEX_OPERATOR_WRITE_NODE = 70, + PM_INDEX_OR_WRITE_NODE = 71, + PM_INSTANCE_VARIABLE_AND_WRITE_NODE = 72, + PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE = 73, + PM_INSTANCE_VARIABLE_OR_WRITE_NODE = 74, + PM_INSTANCE_VARIABLE_READ_NODE = 75, + PM_INSTANCE_VARIABLE_TARGET_NODE = 76, + PM_INSTANCE_VARIABLE_WRITE_NODE = 77, + PM_INTEGER_NODE = 78, + PM_INTERPOLATED_MATCH_LAST_LINE_NODE = 79, + PM_INTERPOLATED_REGULAR_EXPRESSION_NODE = 80, + PM_INTERPOLATED_STRING_NODE = 81, + PM_INTERPOLATED_SYMBOL_NODE = 82, + PM_INTERPOLATED_X_STRING_NODE = 83, + PM_KEYWORD_HASH_NODE = 84, + PM_KEYWORD_PARAMETER_NODE = 85, + PM_KEYWORD_REST_PARAMETER_NODE = 86, + PM_LAMBDA_NODE = 87, + PM_LOCAL_VARIABLE_AND_WRITE_NODE = 88, + PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE = 89, + PM_LOCAL_VARIABLE_OR_WRITE_NODE = 90, + PM_LOCAL_VARIABLE_READ_NODE = 91, + PM_LOCAL_VARIABLE_TARGET_NODE = 92, + PM_LOCAL_VARIABLE_WRITE_NODE = 93, + PM_MATCH_LAST_LINE_NODE = 94, + PM_MATCH_PREDICATE_NODE = 95, + PM_MATCH_REQUIRED_NODE = 96, + PM_MATCH_WRITE_NODE = 97, + PM_MISSING_NODE = 98, + PM_MODULE_NODE = 99, + PM_MULTI_TARGET_NODE = 100, + PM_MULTI_WRITE_NODE = 101, + PM_NEXT_NODE = 102, + PM_NIL_NODE = 103, + PM_NO_KEYWORDS_PARAMETER_NODE = 104, + PM_NUMBERED_REFERENCE_READ_NODE = 105, + PM_OPTIONAL_PARAMETER_NODE = 106, + PM_OR_NODE = 107, + PM_PARAMETERS_NODE = 108, + PM_PARENTHESES_NODE = 109, + PM_PINNED_EXPRESSION_NODE = 110, + PM_PINNED_VARIABLE_NODE = 111, + PM_POST_EXECUTION_NODE = 112, + PM_PRE_EXECUTION_NODE = 113, + PM_PROGRAM_NODE = 114, + PM_RANGE_NODE = 115, + PM_RATIONAL_NODE = 116, + PM_REDO_NODE = 117, + PM_REGULAR_EXPRESSION_NODE = 118, + PM_REQUIRED_PARAMETER_NODE = 119, + PM_RESCUE_MODIFIER_NODE = 120, + PM_RESCUE_NODE = 121, + PM_REST_PARAMETER_NODE = 122, + PM_RETRY_NODE = 123, + PM_RETURN_NODE = 124, + PM_SELF_NODE = 125, + PM_SINGLETON_CLASS_NODE = 126, + PM_SOURCE_ENCODING_NODE = 127, + PM_SOURCE_FILE_NODE = 128, + PM_SOURCE_LINE_NODE = 129, + PM_SPLAT_NODE = 130, + PM_STATEMENTS_NODE = 131, + PM_STRING_CONCAT_NODE = 132, + PM_STRING_NODE = 133, + PM_SUPER_NODE = 134, + PM_SYMBOL_NODE = 135, + PM_TRUE_NODE = 136, + PM_UNDEF_NODE = 137, + PM_UNLESS_NODE = 138, + PM_UNTIL_NODE = 139, + PM_WHEN_NODE = 140, + PM_WHILE_NODE = 141, + PM_X_STRING_NODE = 142, + PM_YIELD_NODE = 143, PM_SCOPE_NODE }; @@ -424,6 +426,8 @@ typedef struct pm_and_node { // ArgumentsNode // // Type: PM_ARGUMENTS_NODE +// Flags: +// PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT typedef struct pm_arguments_node { pm_node_t base; struct pm_node_list arguments; @@ -562,9 +566,6 @@ typedef struct pm_call_and_write_node { struct pm_node *receiver; pm_location_t call_operator_loc; pm_location_t message_loc; - pm_location_t opening_loc; - struct pm_arguments_node *arguments; - pm_location_t closing_loc; pm_constant_id_t read_name; pm_constant_id_t write_name; pm_location_t operator_loc; @@ -600,9 +601,6 @@ typedef struct pm_call_operator_write_node { struct pm_node *receiver; pm_location_t call_operator_loc; pm_location_t message_loc; - pm_location_t opening_loc; - struct pm_arguments_node *arguments; - pm_location_t closing_loc; pm_constant_id_t read_name; pm_constant_id_t write_name; pm_constant_id_t operator; @@ -621,9 +619,6 @@ typedef struct pm_call_or_write_node { struct pm_node *receiver; pm_location_t call_operator_loc; pm_location_t message_loc; - pm_location_t opening_loc; - struct pm_arguments_node *arguments; - pm_location_t closing_loc; pm_constant_id_t read_name; pm_constant_id_t write_name; pm_location_t operator_loc; @@ -1071,8 +1066,8 @@ typedef struct pm_hash_node { typedef struct pm_hash_pattern_node { pm_node_t base; struct pm_node *constant; - struct pm_node_list assocs; - struct pm_node *kwrest; + struct pm_node_list elements; + struct pm_node *rest; pm_location_t opening_loc; pm_location_t closing_loc; } pm_hash_pattern_node_t; @@ -1116,6 +1111,61 @@ typedef struct pm_in_node { pm_location_t then_loc; } pm_in_node_t; +// IndexAndWriteNode +// +// Type: PM_INDEX_AND_WRITE_NODE +// Flags: +// PM_CALL_NODE_FLAGS_SAFE_NAVIGATION +// PM_CALL_NODE_FLAGS_VARIABLE_CALL +typedef struct pm_index_and_write_node { + pm_node_t base; + struct pm_node *receiver; + pm_location_t call_operator_loc; + pm_location_t opening_loc; + struct pm_arguments_node *arguments; + pm_location_t closing_loc; + struct pm_node *block; + pm_location_t operator_loc; + struct pm_node *value; +} pm_index_and_write_node_t; + +// IndexOperatorWriteNode +// +// Type: PM_INDEX_OPERATOR_WRITE_NODE +// Flags: +// PM_CALL_NODE_FLAGS_SAFE_NAVIGATION +// PM_CALL_NODE_FLAGS_VARIABLE_CALL +typedef struct pm_index_operator_write_node { + pm_node_t base; + struct pm_node *receiver; + pm_location_t call_operator_loc; + pm_location_t opening_loc; + struct pm_arguments_node *arguments; + pm_location_t closing_loc; + struct pm_node *block; + pm_constant_id_t operator; + pm_location_t operator_loc; + struct pm_node *value; +} pm_index_operator_write_node_t; + +// IndexOrWriteNode +// +// Type: PM_INDEX_OR_WRITE_NODE +// Flags: +// PM_CALL_NODE_FLAGS_SAFE_NAVIGATION +// PM_CALL_NODE_FLAGS_VARIABLE_CALL +typedef struct pm_index_or_write_node { + pm_node_t base; + struct pm_node *receiver; + pm_location_t call_operator_loc; + pm_location_t opening_loc; + struct pm_arguments_node *arguments; + pm_location_t closing_loc; + struct pm_node *block; + pm_location_t operator_loc; + struct pm_node *value; +} pm_index_or_write_node_t; + // InstanceVariableAndWriteNode // // Type: PM_INSTANCE_VARIABLE_AND_WRITE_NODE @@ -1439,7 +1489,9 @@ typedef struct pm_module_node { // Type: PM_MULTI_TARGET_NODE typedef struct pm_multi_target_node { pm_node_t base; - struct pm_node_list targets; + struct pm_node_list lefts; + struct pm_node *rest; + struct pm_node_list rights; pm_location_t lparen_loc; pm_location_t rparen_loc; } pm_multi_target_node_t; @@ -1449,7 +1501,9 @@ typedef struct pm_multi_target_node { // Type: PM_MULTI_WRITE_NODE typedef struct pm_multi_write_node { pm_node_t base; - struct pm_node_list targets; + struct pm_node_list lefts; + struct pm_node *rest; + struct pm_node_list rights; pm_location_t lparen_loc; pm_location_t rparen_loc; pm_location_t operator_loc; @@ -1632,16 +1686,6 @@ typedef struct pm_regular_expression_node { pm_string_t unescaped; } pm_regular_expression_node_t; -// RequiredDestructuredParameterNode -// -// Type: PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE -typedef struct pm_required_destructured_parameter_node { - pm_node_t base; - struct pm_node_list parameters; - pm_location_t opening_loc; - pm_location_t closing_loc; -} pm_required_destructured_parameter_node_t; - // RequiredParameterNode // // Type: PM_REQUIRED_PARAMETER_NODE @@ -1889,6 +1933,11 @@ typedef struct pm_yield_node { pm_location_t rparen_loc; } pm_yield_node_t; +// ArgumentsNodeFlags +typedef enum pm_arguments_node_flags { + PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT = 1 << 0, +} pm_arguments_node_flags_t; + // CallNodeFlags typedef enum pm_call_node_flags { PM_CALL_NODE_FLAGS_SAFE_NAVIGATION = 1 << 0, diff --git a/src/main/c/yarp/include/prism/diagnostic.h b/src/main/c/yarp/include/prism/diagnostic.h index 062ba07d4287..0c9e4a3fd1e9 100644 --- a/src/main/c/yarp/include/prism/diagnostic.h +++ b/src/main/c/yarp/include/prism/diagnostic.h @@ -158,6 +158,7 @@ typedef enum { PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE, PM_ERR_OPERATOR_MULTI_ASSIGN, + PM_ERR_OPERATOR_WRITE_ARGUMENTS, PM_ERR_OPERATOR_WRITE_BLOCK, PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI, PM_ERR_PARAMETER_BLOCK_MULTI, diff --git a/src/main/c/yarp/include/prism/node.h b/src/main/c/yarp/include/prism/node.h index 403e84e0d3ed..71b364046a77 100644 --- a/src/main/c/yarp/include/prism/node.h +++ b/src/main/c/yarp/include/prism/node.h @@ -29,21 +29,4 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ #define PM_EMPTY_NODE_LIST ((pm_node_list_t) { .nodes = NULL, .size = 0, .capacity = 0 }) -// ScopeNodes are helper nodes, and will never be part of the AST. We manually -// declare them here to avoid generating them. -typedef struct pm_scope_node { - pm_node_t base; - struct pm_scope_node *previous; - pm_node_t *ast_node; - struct pm_parameters_node *parameters; - pm_node_t *body; - pm_constant_id_list_t locals; - pm_parser_t *parser; - - // We don't have the CRuby types ID and st_table within Prism - // so we use void * - void *constants; // ID *constants - void *index_lookup_table; // st_table *index_lookup_table -} pm_scope_node_t; - #endif // PRISM_NODE_H diff --git a/src/main/c/yarp/include/prism/parser.h b/src/main/c/yarp/include/prism/parser.h index f77d8818aae1..c701e595a9f3 100644 --- a/src/main/c/yarp/include/prism/parser.h +++ b/src/main/c/yarp/include/prism/parser.h @@ -212,6 +212,7 @@ typedef enum { PM_CONTEXT_EMBEXPR, // an interpolated expression PM_CONTEXT_ENSURE, // an ensure statement PM_CONTEXT_FOR, // a for loop + PM_CONTEXT_FOR_INDEX, // a for loop's index PM_CONTEXT_IF, // an if statement PM_CONTEXT_LAMBDA_BRACES, // a lambda expression with braces PM_CONTEXT_LAMBDA_DO_END, // a lambda expression with do..end diff --git a/src/main/c/yarp/include/prism/prettyprint.h b/src/main/c/yarp/include/prism/prettyprint.h new file mode 100644 index 000000000000..04596793d47b --- /dev/null +++ b/src/main/c/yarp/include/prism/prettyprint.h @@ -0,0 +1,15 @@ +#ifndef PRISM_PRETTYPRINT_H +#define PRISM_PRETTYPRINT_H + +#include "prism/defines.h" + +#include + +#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/src/main/c/yarp/include/prism/util/pm_buffer.h b/src/main/c/yarp/include/prism/util/pm_buffer.h index d881b3244187..b8b7c41a1070 100644 --- a/src/main/c/yarp/include/prism/util/pm_buffer.h +++ b/src/main/c/yarp/include/prism/util/pm_buffer.h @@ -13,9 +13,9 @@ // block of memory. It is used to store the serialized representation of a // prism tree. typedef struct { - char *value; size_t length; size_t capacity; + char *value; } pm_buffer_t; // Return the size of the pm_buffer_t struct. @@ -36,17 +36,23 @@ 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_str(pm_buffer_t *buffer, const char *value, size_t length); +void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length); // Append a list of bytes to the buffer. void pm_buffer_append_bytes(pm_buffer_t *buffer, const uint8_t *value, size_t length); // Append a single byte to the buffer. -void pm_buffer_append_u8(pm_buffer_t *buffer, uint8_t value); +void pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value); // Append a 32-bit unsigned integer to the buffer. -void pm_buffer_append_u32(pm_buffer_t *buffer, uint32_t value); +void pm_buffer_append_varint(pm_buffer_t *buffer, uint32_t value); + +// Append one buffer onto another. +void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source); // Free the memory associated with the buffer. PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer); diff --git a/src/main/c/yarp/include/prism/util/pm_constant_pool.h b/src/main/c/yarp/include/prism/util/pm_constant_pool.h index 3ea335ac52f4..fa9081f737d1 100644 --- a/src/main/c/yarp/include/prism/util/pm_constant_pool.h +++ b/src/main/c/yarp/include/prism/util/pm_constant_pool.h @@ -39,9 +39,21 @@ size_t pm_constant_id_list_memsize(pm_constant_id_list_t *list); // Free the memory associated with a list of constant ids. void pm_constant_id_list_free(pm_constant_id_list_t *list); +// Constant pool buckets can have a couple of different types. +typedef unsigned int pm_constant_pool_bucket_type_t; + +// By default, each constant is a slice of the source. +static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_DEFAULT = 0; + +// An owned constant is one for which memory has been allocated. +static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_OWNED = 1; + +// A constant constant is known at compile time. +static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_CONSTANT = 2; + typedef struct { - unsigned int id: 31; - bool owned: 1; + unsigned int id: 30; + pm_constant_pool_bucket_type_t type: 2; uint32_t hash; } pm_constant_pool_bucket_t; @@ -63,10 +75,8 @@ typedef struct { // Initialize a new constant pool with a given capacity. bool pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity); -static inline pm_constant_t* pm_constant_pool_id_to_constant(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]; -} +// Return a pointer to the constant indicated by the given 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. @@ -77,6 +87,10 @@ pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const // resize fail. pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, const uint8_t *start, size_t length); +// Insert a constant into a constant pool from memory that is constant. Returns +// the id of the constant, or 0 if any potential calls to resize fail. +pm_constant_id_t pm_constant_pool_insert_constant(pm_constant_pool_t *pool, const uint8_t *start, size_t length); + // Free the memory associated with a constant pool. void pm_constant_pool_free(pm_constant_pool_t *pool); diff --git a/src/main/c/yarp/include/prism/util/pm_newline_list.h b/src/main/c/yarp/include/prism/util/pm_newline_list.h index 38fb40196d58..da6c565d6bc7 100644 --- a/src/main/c/yarp/include/prism/util/pm_newline_list.h +++ b/src/main/c/yarp/include/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); diff --git a/src/main/c/yarp/include/prism/version.h b/src/main/c/yarp/include/prism/version.h index 8787b40ae1a9..55ed5da7038e 100644 --- a/src/main/c/yarp/include/prism/version.h +++ b/src/main/c/yarp/include/prism/version.h @@ -1,4 +1,4 @@ #define PRISM_VERSION_MAJOR 0 -#define PRISM_VERSION_MINOR 14 -#define PRISM_VERSION_PATCH 0 -#define PRISM_VERSION "0.14.0" +#define PRISM_VERSION_MINOR 15 +#define PRISM_VERSION_PATCH 1 +#define PRISM_VERSION "0.15.1" diff --git a/src/main/c/yarp/src/diagnostic.c b/src/main/c/yarp/src/diagnostic.c index 09388297bafa..b10670809934 100644 --- a/src/main/c/yarp/src/diagnostic.c +++ b/src/main/c/yarp/src/diagnostic.c @@ -192,6 +192,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED] = "Numbered parameters are not allowed alongside explicit parameters", [PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE] = "Numbered parameter is already used in outer scope", [PM_ERR_OPERATOR_MULTI_ASSIGN] = "Unexpected operator for a multiple assignment", + [PM_ERR_OPERATOR_WRITE_ARGUMENTS] = "Unexpected operator after a call with arguments", [PM_ERR_OPERATOR_WRITE_BLOCK] = "Unexpected operator after a call with a block", [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = "Unexpected multiple `**` splat parameters", [PM_ERR_PARAMETER_BLOCK_MULTI] = "Multiple block parameters; only one block is allowed", diff --git a/src/main/c/yarp/src/node.c b/src/main/c/yarp/src/node.c index ad35ba6fa4c3..2744f2c99356 100644 --- a/src/main/c/yarp/src/node.c +++ b/src/main/c/yarp/src/node.c @@ -201,9 +201,6 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { if (cast->receiver != NULL) { pm_node_destroy(parser, (pm_node_t *)cast->receiver); } - if (cast->arguments != NULL) { - pm_node_destroy(parser, (pm_node_t *)cast->arguments); - } pm_node_destroy(parser, (pm_node_t *)cast->value); break; } @@ -227,9 +224,6 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { if (cast->receiver != NULL) { pm_node_destroy(parser, (pm_node_t *)cast->receiver); } - if (cast->arguments != NULL) { - pm_node_destroy(parser, (pm_node_t *)cast->arguments); - } pm_node_destroy(parser, (pm_node_t *)cast->value); break; } @@ -239,9 +233,6 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { if (cast->receiver != NULL) { pm_node_destroy(parser, (pm_node_t *)cast->receiver); } - if (cast->arguments != NULL) { - pm_node_destroy(parser, (pm_node_t *)cast->arguments); - } pm_node_destroy(parser, (pm_node_t *)cast->value); break; } @@ -538,9 +529,9 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { if (cast->constant != NULL) { pm_node_destroy(parser, (pm_node_t *)cast->constant); } - pm_node_list_free(parser, &cast->assocs); - if (cast->kwrest != NULL) { - pm_node_destroy(parser, (pm_node_t *)cast->kwrest); + pm_node_list_free(parser, &cast->elements); + if (cast->rest != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->rest); } break; } @@ -577,6 +568,51 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { } break; } +#line 57 "node.c.erb" + case PM_INDEX_AND_WRITE_NODE: { + pm_index_and_write_node_t *cast = (pm_index_and_write_node_t *) node; + if (cast->receiver != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->receiver); + } + if (cast->arguments != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->arguments); + } + if (cast->block != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->block); + } + pm_node_destroy(parser, (pm_node_t *)cast->value); + break; + } +#line 57 "node.c.erb" + case PM_INDEX_OPERATOR_WRITE_NODE: { + pm_index_operator_write_node_t *cast = (pm_index_operator_write_node_t *) node; + if (cast->receiver != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->receiver); + } + if (cast->arguments != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->arguments); + } + if (cast->block != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->block); + } + pm_node_destroy(parser, (pm_node_t *)cast->value); + break; + } +#line 57 "node.c.erb" + case PM_INDEX_OR_WRITE_NODE: { + pm_index_or_write_node_t *cast = (pm_index_or_write_node_t *) node; + if (cast->receiver != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->receiver); + } + if (cast->arguments != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->arguments); + } + if (cast->block != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->block); + } + pm_node_destroy(parser, (pm_node_t *)cast->value); + break; + } #line 57 "node.c.erb" case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { pm_instance_variable_and_write_node_t *cast = (pm_instance_variable_and_write_node_t *) node; @@ -749,13 +785,21 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { #line 57 "node.c.erb" case PM_MULTI_TARGET_NODE: { pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node; - pm_node_list_free(parser, &cast->targets); + pm_node_list_free(parser, &cast->lefts); + if (cast->rest != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->rest); + } + pm_node_list_free(parser, &cast->rights); break; } #line 57 "node.c.erb" case PM_MULTI_WRITE_NODE: { pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node; - pm_node_list_free(parser, &cast->targets); + pm_node_list_free(parser, &cast->lefts); + if (cast->rest != NULL) { + pm_node_destroy(parser, (pm_node_t *)cast->rest); + } + pm_node_list_free(parser, &cast->rights); pm_node_destroy(parser, (pm_node_t *)cast->value); break; } @@ -880,12 +924,6 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { pm_string_free(&cast->unescaped); break; } -#line 57 "node.c.erb" - case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { - pm_required_destructured_parameter_node_t *cast = (pm_required_destructured_parameter_node_t *) node; - pm_node_list_free(parser, &cast->parameters); - break; - } #line 57 "node.c.erb" case PM_REQUIRED_PARAMETER_NODE: { break; @@ -1253,9 +1291,6 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { if (cast->receiver != NULL) { pm_node_memsize_node((pm_node_t *)cast->receiver, memsize); } - if (cast->arguments != NULL) { - pm_node_memsize_node((pm_node_t *)cast->arguments, memsize); - } pm_node_memsize_node((pm_node_t *)cast->value, memsize); break; } @@ -1281,9 +1316,6 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { if (cast->receiver != NULL) { pm_node_memsize_node((pm_node_t *)cast->receiver, memsize); } - if (cast->arguments != NULL) { - pm_node_memsize_node((pm_node_t *)cast->arguments, memsize); - } pm_node_memsize_node((pm_node_t *)cast->value, memsize); break; } @@ -1294,9 +1326,6 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { if (cast->receiver != NULL) { pm_node_memsize_node((pm_node_t *)cast->receiver, memsize); } - if (cast->arguments != NULL) { - pm_node_memsize_node((pm_node_t *)cast->arguments, memsize); - } pm_node_memsize_node((pm_node_t *)cast->value, memsize); break; } @@ -1658,9 +1687,9 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { if (cast->constant != NULL) { pm_node_memsize_node((pm_node_t *)cast->constant, memsize); } - memsize->memsize += pm_node_list_memsize(&cast->assocs, memsize); - if (cast->kwrest != NULL) { - pm_node_memsize_node((pm_node_t *)cast->kwrest, memsize); + memsize->memsize += pm_node_list_memsize(&cast->elements, memsize); + if (cast->rest != NULL) { + pm_node_memsize_node((pm_node_t *)cast->rest, memsize); } break; } @@ -1701,6 +1730,54 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { } break; } +#line 102 "node.c.erb" + case PM_INDEX_AND_WRITE_NODE: { + pm_index_and_write_node_t *cast = (pm_index_and_write_node_t *) node; + memsize->memsize += sizeof(*cast); + if (cast->receiver != NULL) { + pm_node_memsize_node((pm_node_t *)cast->receiver, memsize); + } + if (cast->arguments != NULL) { + pm_node_memsize_node((pm_node_t *)cast->arguments, memsize); + } + if (cast->block != NULL) { + pm_node_memsize_node((pm_node_t *)cast->block, memsize); + } + pm_node_memsize_node((pm_node_t *)cast->value, memsize); + break; + } +#line 102 "node.c.erb" + case PM_INDEX_OPERATOR_WRITE_NODE: { + pm_index_operator_write_node_t *cast = (pm_index_operator_write_node_t *) node; + memsize->memsize += sizeof(*cast); + if (cast->receiver != NULL) { + pm_node_memsize_node((pm_node_t *)cast->receiver, memsize); + } + if (cast->arguments != NULL) { + pm_node_memsize_node((pm_node_t *)cast->arguments, memsize); + } + if (cast->block != NULL) { + pm_node_memsize_node((pm_node_t *)cast->block, memsize); + } + pm_node_memsize_node((pm_node_t *)cast->value, memsize); + break; + } +#line 102 "node.c.erb" + case PM_INDEX_OR_WRITE_NODE: { + pm_index_or_write_node_t *cast = (pm_index_or_write_node_t *) node; + memsize->memsize += sizeof(*cast); + if (cast->receiver != NULL) { + pm_node_memsize_node((pm_node_t *)cast->receiver, memsize); + } + if (cast->arguments != NULL) { + pm_node_memsize_node((pm_node_t *)cast->arguments, memsize); + } + if (cast->block != NULL) { + pm_node_memsize_node((pm_node_t *)cast->block, memsize); + } + pm_node_memsize_node((pm_node_t *)cast->value, memsize); + break; + } #line 102 "node.c.erb" case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { pm_instance_variable_and_write_node_t *cast = (pm_instance_variable_and_write_node_t *) node; @@ -1928,8 +2005,12 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node; memsize->memsize += sizeof(*cast); // Node lists will add in their own sizes below. - memsize->memsize -= sizeof(pm_node_list_t) * 1; - memsize->memsize += pm_node_list_memsize(&cast->targets, memsize); + memsize->memsize -= sizeof(pm_node_list_t) * 2; + memsize->memsize += pm_node_list_memsize(&cast->lefts, memsize); + if (cast->rest != NULL) { + pm_node_memsize_node((pm_node_t *)cast->rest, memsize); + } + memsize->memsize += pm_node_list_memsize(&cast->rights, memsize); break; } #line 102 "node.c.erb" @@ -1937,8 +2018,12 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node; memsize->memsize += sizeof(*cast); // Node lists will add in their own sizes below. - memsize->memsize -= sizeof(pm_node_list_t) * 1; - memsize->memsize += pm_node_list_memsize(&cast->targets, memsize); + memsize->memsize -= sizeof(pm_node_list_t) * 2; + memsize->memsize += pm_node_list_memsize(&cast->lefts, memsize); + if (cast->rest != NULL) { + pm_node_memsize_node((pm_node_t *)cast->rest, memsize); + } + memsize->memsize += pm_node_list_memsize(&cast->rights, memsize); pm_node_memsize_node((pm_node_t *)cast->value, memsize); break; } @@ -2088,15 +2173,6 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { memsize->memsize += pm_string_memsize(&cast->unescaped); break; } -#line 102 "node.c.erb" - case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { - pm_required_destructured_parameter_node_t *cast = (pm_required_destructured_parameter_node_t *) node; - memsize->memsize += sizeof(*cast); - // Node lists will add in their own sizes below. - memsize->memsize -= sizeof(pm_node_list_t) * 1; - memsize->memsize += pm_node_list_memsize(&cast->parameters, memsize); - break; - } #line 102 "node.c.erb" case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t *cast = (pm_required_parameter_node_t *) node; @@ -2468,6 +2544,12 @@ pm_node_type_to_str(pm_node_type_t node_type) return "PM_IMPLICIT_NODE"; case PM_IN_NODE: return "PM_IN_NODE"; + case PM_INDEX_AND_WRITE_NODE: + return "PM_INDEX_AND_WRITE_NODE"; + case PM_INDEX_OPERATOR_WRITE_NODE: + return "PM_INDEX_OPERATOR_WRITE_NODE"; + case PM_INDEX_OR_WRITE_NODE: + return "PM_INDEX_OR_WRITE_NODE"; case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: return "PM_INSTANCE_VARIABLE_AND_WRITE_NODE"; case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: @@ -2562,8 +2644,6 @@ pm_node_type_to_str(pm_node_type_t node_type) return "PM_REDO_NODE"; case PM_REGULAR_EXPRESSION_NODE: return "PM_REGULAR_EXPRESSION_NODE"; - case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: - return "PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE"; case PM_REQUIRED_PARAMETER_NODE: return "PM_REQUIRED_PARAMETER_NODE"; case PM_RESCUE_MODIFIER_NODE: diff --git a/src/main/c/yarp/src/prettyprint.c b/src/main/c/yarp/src/prettyprint.c index f07cfe83b4ab..8afd2e751c54 100644 --- a/src/main/c/yarp/src/prettyprint.c +++ b/src/main/c/yarp/src/prettyprint.c @@ -5,2135 +5,8216 @@ /* if you are looking to modify the */ /* template */ /******************************************************************************/ -#include "prism/defines.h" +#include "prism/prettyprint.h" -#include +static void +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]; -#include "prism/ast.h" -#include "prism/parser.h" -#include "prism/util/pm_buffer.h" + 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, '\\'); + } + } -static void -prettyprint_location(pm_buffer_t *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_str(buffer, printed, strlen(printed)); + 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 *buffer, pm_parser_t *parser, pm_node_t *node) { +prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node, pm_buffer_t *prefix_buffer) { switch (PM_NODE_TYPE(node)) { - // We do not need to print a ScopeNode as it's not part - // of the AST case PM_SCOPE_NODE: + // We do not need to print a ScopeNode as it's not part of the AST. return; case PM_ALIAS_GLOBAL_VARIABLE_NODE: { - pm_buffer_append_str(buffer, "AliasGlobalVariableNode(", 24); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_alias_global_variable_node_t *)node)->new_name); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_alias_global_variable_node_t *)node)->old_name); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_alias_global_variable_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_alias_global_variable_node_t *cast = (pm_alias_global_variable_node_t *) node; + pm_buffer_append_string(output_buffer, "@ AliasGlobalVariableNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // new_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── new_name:", 19); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->new_name, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // old_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── old_name:", 19); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->old_name, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_ALIAS_METHOD_NODE: { - pm_buffer_append_str(buffer, "AliasMethodNode(", 16); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_alias_method_node_t *)node)->new_name); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_alias_method_node_t *)node)->old_name); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_alias_method_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_alias_method_node_t *cast = (pm_alias_method_node_t *) node; + pm_buffer_append_string(output_buffer, "@ AliasMethodNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // new_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── new_name:", 19); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->new_name, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // old_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── old_name:", 19); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->old_name, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_ALTERNATION_PATTERN_NODE: { - pm_buffer_append_str(buffer, "AlternationPatternNode(", 23); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_alternation_pattern_node_t *)node)->left); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_alternation_pattern_node_t *)node)->right); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_alternation_pattern_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_alternation_pattern_node_t *cast = (pm_alternation_pattern_node_t *) node; + pm_buffer_append_string(output_buffer, "@ AlternationPatternNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── right:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_AND_NODE: { - pm_buffer_append_str(buffer, "AndNode(", 8); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_and_node_t *)node)->left); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_and_node_t *)node)->right); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_and_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_and_node_t *cast = (pm_and_node_t *) node; + pm_buffer_append_string(output_buffer, "@ AndNode (location: ", 21); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── right:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_ARGUMENTS_NODE: { - pm_buffer_append_str(buffer, "ArgumentsNode(", 14); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_arguments_node_t *)node)->arguments.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_arguments_node_t *) node)->arguments.nodes[index]); + pm_arguments_node_t *cast = (pm_arguments_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ArgumentsNode (location: ", 27); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->arguments.size); + + size_t last_index = cast->arguments.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " keyword_splat", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_ARRAY_NODE: { - pm_buffer_append_str(buffer, "ArrayNode(", 10); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_array_node_t *)node)->elements.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_array_node_t *) node)->elements.nodes[index]); + pm_array_node_t *cast = (pm_array_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ArrayNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // elements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── elements:", 19); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->elements.size); + + size_t last_index = cast->elements.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->elements.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_array_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_array_node_t *)node)->opening_loc); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_array_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_array_node_t *)node)->closing_loc); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_ARRAY_PATTERN_NODE: { - pm_buffer_append_str(buffer, "ArrayPatternNode(", 17); - if (((pm_array_pattern_node_t *)node)->constant == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_array_pattern_node_t *)node)->constant); - } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_array_pattern_node_t *)node)->requireds.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_array_pattern_node_t *) node)->requireds.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_array_pattern_node_t *)node)->rest == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_array_pattern_node_t *)node)->rest); - } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_array_pattern_node_t *)node)->posts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_array_pattern_node_t *) node)->posts.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_array_pattern_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_array_pattern_node_t *)node)->opening_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_array_pattern_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_array_pattern_node_t *)node)->closing_loc); - } - pm_buffer_append_str(buffer, ")", 1); + pm_array_pattern_node_t *cast = (pm_array_pattern_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ArrayPatternNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // constant + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── constant:", 19); + if (cast->constant == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->constant, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // requireds + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── requireds:", 20); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->requireds.size); + + size_t last_index = cast->requireds.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->requireds.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // rest + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rest:", 15); + if (cast->rest == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rest, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // posts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── posts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->posts.size); + + size_t last_index = cast->posts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->posts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + break; } case PM_ASSOC_NODE: { - pm_buffer_append_str(buffer, "AssocNode(", 10); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_assoc_node_t *)node)->key); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_assoc_node_t *)node)->value == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_assoc_node_t *)node)->value); + pm_assoc_node_t *cast = (pm_assoc_node_t *) node; + pm_buffer_append_string(output_buffer, "@ AssocNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // key + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── key:", 14); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->key, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + if (cast->value == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_assoc_node_t *)node)->operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_assoc_node_t *)node)->operator_loc); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_ASSOC_SPLAT_NODE: { - pm_buffer_append_str(buffer, "AssocSplatNode(", 15); - if (((pm_assoc_splat_node_t *)node)->value == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_assoc_splat_node_t *)node)->value); + pm_assoc_splat_node_t *cast = (pm_assoc_splat_node_t *) node; + pm_buffer_append_string(output_buffer, "@ AssocSplatNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + if (cast->value == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_assoc_splat_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_BACK_REFERENCE_READ_NODE: { - pm_buffer_append_str(buffer, "BackReferenceReadNode(", 22); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_back_reference_read_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_back_reference_read_node_t *cast = (pm_back_reference_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BackReferenceReadNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_BEGIN_NODE: { - pm_buffer_append_str(buffer, "BeginNode(", 10); - if (((pm_begin_node_t *)node)->begin_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_begin_node_t *)node)->begin_keyword_loc); + pm_begin_node_t *cast = (pm_begin_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BeginNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // begin_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── begin_keyword_loc:", 28); + pm_location_t *location = &cast->begin_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_begin_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_begin_node_t *)node)->statements); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_begin_node_t *)node)->rescue_clause == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_begin_node_t *)node)->rescue_clause); + + // rescue_clause + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rescue_clause:", 24); + if (cast->rescue_clause == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rescue_clause, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_begin_node_t *)node)->else_clause == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_begin_node_t *)node)->else_clause); + + // else_clause + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── else_clause:", 22); + if (cast->else_clause == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->else_clause, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_begin_node_t *)node)->ensure_clause == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_begin_node_t *)node)->ensure_clause); + + // ensure_clause + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── ensure_clause:", 24); + if (cast->ensure_clause == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->ensure_clause, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_begin_node_t *)node)->end_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_begin_node_t *)node)->end_keyword_loc); + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_BLOCK_ARGUMENT_NODE: { - pm_buffer_append_str(buffer, "BlockArgumentNode(", 18); - if (((pm_block_argument_node_t *)node)->expression == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_block_argument_node_t *)node)->expression); + pm_block_argument_node_t *cast = (pm_block_argument_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BlockArgumentNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // expression + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── expression:", 21); + if (cast->expression == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->expression, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_block_argument_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_BLOCK_LOCAL_VARIABLE_NODE: { - pm_buffer_append_str(buffer, "BlockLocalVariableNode(", 23); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_block_local_variable_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_block_local_variable_node_t *cast = (pm_block_local_variable_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BlockLocalVariableNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_BLOCK_NODE: { - pm_buffer_append_str(buffer, "BlockNode(", 10); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_block_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_block_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_block_node_t *)node)->parameters == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_block_node_t *)node)->parameters); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_block_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_block_node_t *)node)->body); - } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_block_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_block_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_block_node_t *cast = (pm_block_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BlockNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } + + // parameters + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parameters:", 21); + if (cast->parameters == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parameters, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_BLOCK_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "BlockParameterNode(", 19); - if (((pm_block_parameter_node_t *)node)->name == 0) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_block_parameter_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); + pm_block_parameter_node_t *cast = (pm_block_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BlockParameterNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + if (cast->name == 0) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_block_parameter_node_t *)node)->name_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_block_parameter_node_t *)node)->name_loc); + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_block_parameter_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_BLOCK_PARAMETERS_NODE: { - pm_buffer_append_str(buffer, "BlockParametersNode(", 20); - if (((pm_block_parameters_node_t *)node)->parameters == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_block_parameters_node_t *)node)->parameters); + pm_block_parameters_node_t *cast = (pm_block_parameters_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BlockParametersNode (location: ", 33); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // parameters + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parameters:", 21); + if (cast->parameters == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parameters, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_block_parameters_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_block_parameters_node_t *) node)->locals.nodes[index]); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->locals.size); + + size_t last_index = cast->locals.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->locals.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_block_parameters_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_block_parameters_node_t *)node)->opening_loc); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_block_parameters_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_block_parameters_node_t *)node)->closing_loc); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_BREAK_NODE: { - pm_buffer_append_str(buffer, "BreakNode(", 10); - if (((pm_break_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_break_node_t *)node)->arguments); + pm_break_node_t *cast = (pm_break_node_t *) node; + pm_buffer_append_string(output_buffer, "@ BreakNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_break_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_CALL_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "CallAndWriteNode(", 17); - if (((pm_call_and_write_node_t *)node)->receiver == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_and_write_node_t *)node)->receiver); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_and_write_node_t *)node)->call_operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_and_write_node_t *)node)->call_operator_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_and_write_node_t *)node)->message_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_and_write_node_t *)node)->message_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_and_write_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_and_write_node_t *)node)->opening_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_and_write_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_and_write_node_t *)node)->arguments); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_and_write_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_and_write_node_t *)node)->closing_loc); - } - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char read_name_buffer[12]; - snprintf(read_name_buffer, sizeof(read_name_buffer), "%u", ((pm_call_and_write_node_t *)node)->read_name); - pm_buffer_append_str(buffer, read_name_buffer, strlen(read_name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char write_name_buffer[12]; - snprintf(write_name_buffer, sizeof(write_name_buffer), "%u", ((pm_call_and_write_node_t *)node)->write_name); - pm_buffer_append_str(buffer, write_name_buffer, strlen(write_name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_call_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_call_and_write_node_t *cast = (pm_call_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ CallAndWriteNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // message_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── message_loc:", 22); + pm_location_t *location = &cast->message_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // read_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── read_name:", 20); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->read_name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // write_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── write_name:", 21); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->write_name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CALL_NODE: { - pm_buffer_append_str(buffer, "CallNode(", 9); - if (((pm_call_node_t *)node)->receiver == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_node_t *)node)->receiver); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_node_t *)node)->call_operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_node_t *)node)->call_operator_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_node_t *)node)->message_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_node_t *)node)->message_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_node_t *)node)->opening_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_node_t *)node)->arguments); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_node_t *)node)->closing_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_node_t *)node)->block == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_node_t *)node)->block); - } - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_call_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_call_node_t *cast = (pm_call_node_t *) node; + pm_buffer_append_string(output_buffer, "@ CallNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // message_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── message_loc:", 22); + pm_location_t *location = &cast->message_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CALL_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "CallOperatorWriteNode(", 22); - if (((pm_call_operator_write_node_t *)node)->receiver == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_operator_write_node_t *)node)->receiver); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_operator_write_node_t *)node)->call_operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_operator_write_node_t *)node)->call_operator_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_operator_write_node_t *)node)->message_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_operator_write_node_t *)node)->message_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_operator_write_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_operator_write_node_t *)node)->opening_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_operator_write_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_operator_write_node_t *)node)->arguments); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_operator_write_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_operator_write_node_t *)node)->closing_loc); - } - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char read_name_buffer[12]; - snprintf(read_name_buffer, sizeof(read_name_buffer), "%u", ((pm_call_operator_write_node_t *)node)->read_name); - pm_buffer_append_str(buffer, read_name_buffer, strlen(read_name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char write_name_buffer[12]; - snprintf(write_name_buffer, sizeof(write_name_buffer), "%u", ((pm_call_operator_write_node_t *)node)->write_name); - pm_buffer_append_str(buffer, write_name_buffer, strlen(write_name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_call_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_call_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_call_operator_write_node_t *cast = (pm_call_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ CallOperatorWriteNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // message_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── message_loc:", 22); + pm_location_t *location = &cast->message_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // read_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── read_name:", 20); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->read_name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // write_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── write_name:", 21); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->write_name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CALL_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "CallOrWriteNode(", 16); - if (((pm_call_or_write_node_t *)node)->receiver == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_or_write_node_t *)node)->receiver); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_or_write_node_t *)node)->call_operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_or_write_node_t *)node)->call_operator_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_or_write_node_t *)node)->message_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_or_write_node_t *)node)->message_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_or_write_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_or_write_node_t *)node)->opening_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_or_write_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_or_write_node_t *)node)->arguments); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_call_or_write_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_call_or_write_node_t *)node)->closing_loc); - } - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char read_name_buffer[12]; - snprintf(read_name_buffer, sizeof(read_name_buffer), "%u", ((pm_call_or_write_node_t *)node)->read_name); - pm_buffer_append_str(buffer, read_name_buffer, strlen(read_name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char write_name_buffer[12]; - snprintf(write_name_buffer, sizeof(write_name_buffer), "%u", ((pm_call_or_write_node_t *)node)->write_name); - pm_buffer_append_str(buffer, write_name_buffer, strlen(write_name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_call_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_call_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_call_or_write_node_t *cast = (pm_call_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ CallOrWriteNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // message_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── message_loc:", 22); + pm_location_t *location = &cast->message_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // read_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── read_name:", 20); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->read_name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // write_name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── write_name:", 21); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->write_name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CAPTURE_PATTERN_NODE: { - pm_buffer_append_str(buffer, "CapturePatternNode(", 19); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_capture_pattern_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_capture_pattern_node_t *)node)->target); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_capture_pattern_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_capture_pattern_node_t *cast = (pm_capture_pattern_node_t *) node; + pm_buffer_append_string(output_buffer, "@ CapturePatternNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // target + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── target:", 17); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->target, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_CASE_NODE: { - pm_buffer_append_str(buffer, "CaseNode(", 9); - if (((pm_case_node_t *)node)->predicate == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_case_node_t *)node)->predicate); + pm_case_node_t *cast = (pm_case_node_t *) node; + pm_buffer_append_string(output_buffer, "@ CaseNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // predicate + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── predicate:", 20); + if (cast->predicate == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->predicate, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // conditions + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── conditions:", 21); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->conditions.size); + + size_t last_index = cast->conditions.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->conditions.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // consequent + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── consequent:", 21); + if (cast->consequent == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->consequent, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_case_node_t *)node)->conditions.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_case_node_t *) node)->conditions.nodes[index]); + + // case_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── case_keyword_loc:", 27); + pm_location_t *location = &cast->case_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_case_node_t *)node)->consequent == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_case_node_t *)node)->consequent); + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_case_node_t *)node)->case_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_case_node_t *)node)->end_keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_CLASS_NODE: { - pm_buffer_append_str(buffer, "ClassNode(", 10); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_class_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_class_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_node_t *)node)->class_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_node_t *)node)->constant_path); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_class_node_t *)node)->inheritance_operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_class_node_t *)node)->inheritance_operator_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_class_node_t *)node)->superclass == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_node_t *)node)->superclass); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_class_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_node_t *)node)->body); - } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_node_t *)node)->end_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); - break; - } - case PM_CLASS_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "ClassVariableAndWriteNode(", 26); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_variable_and_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_and_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_variable_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); - break; - } - case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "ClassVariableOperatorWriteNode(", 31); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_variable_operator_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_operator_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_variable_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_class_variable_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ")", 1); - break; + pm_class_node_t *cast = (pm_class_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } + + // class_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── class_keyword_loc:", 28); + pm_location_t *location = &cast->class_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // constant_path + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── constant_path:", 24); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->constant_path, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // inheritance_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── inheritance_operator_loc:", 35); + pm_location_t *location = &cast->inheritance_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // superclass + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── superclass:", 21); + if (cast->superclass == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->superclass, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + break; + } + case PM_CLASS_VARIABLE_AND_WRITE_NODE: { + pm_class_variable_and_write_node_t *cast = (pm_class_variable_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassVariableAndWriteNode (location: ", 39); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + break; + } + case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { + pm_class_variable_operator_write_node_t *cast = (pm_class_variable_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassVariableOperatorWriteNode (location: ", 44); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + + break; } case PM_CLASS_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "ClassVariableOrWriteNode(", 25); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_variable_or_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_or_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_variable_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_class_variable_or_write_node_t *cast = (pm_class_variable_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassVariableOrWriteNode (location: ", 38); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CLASS_VARIABLE_READ_NODE: { - pm_buffer_append_str(buffer, "ClassVariableReadNode(", 22); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_variable_read_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_class_variable_read_node_t *cast = (pm_class_variable_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassVariableReadNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CLASS_VARIABLE_TARGET_NODE: { - pm_buffer_append_str(buffer, "ClassVariableTargetNode(", 24); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_variable_target_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_class_variable_target_node_t *cast = (pm_class_variable_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassVariableTargetNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CLASS_VARIABLE_WRITE_NODE: { - pm_buffer_append_str(buffer, "ClassVariableWriteNode(", 23); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_class_variable_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_class_variable_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_class_variable_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_class_variable_write_node_t *)node)->operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_class_variable_write_node_t *)node)->operator_loc); + pm_class_variable_write_node_t *cast = (pm_class_variable_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ClassVariableWriteNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_CONSTANT_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantAndWriteNode(", 21); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_constant_and_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_and_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_and_write_node_t *cast = (pm_constant_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantAndWriteNode (location: ", 34); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CONSTANT_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantOperatorWriteNode(", 26); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_constant_operator_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_operator_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_constant_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_operator_write_node_t *cast = (pm_constant_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantOperatorWriteNode (location: ", 39); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CONSTANT_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantOrWriteNode(", 20); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_constant_or_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_or_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_or_write_node_t *cast = (pm_constant_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantOrWriteNode (location: ", 33); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CONSTANT_PATH_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantPathAndWriteNode(", 25); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_and_write_node_t *)node)->target); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_path_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_path_and_write_node_t *cast = (pm_constant_path_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantPathAndWriteNode (location: ", 38); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // target + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── target:", 17); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->target, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CONSTANT_PATH_NODE: { - pm_buffer_append_str(buffer, "ConstantPathNode(", 17); - if (((pm_constant_path_node_t *)node)->parent == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_node_t *)node)->parent); + pm_constant_path_node_t *cast = (pm_constant_path_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantPathNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // parent + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parent:", 17); + if (cast->parent == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parent, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // child + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── child:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->child, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_node_t *)node)->child); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_path_node_t *)node)->delimiter_loc); - pm_buffer_append_str(buffer, ")", 1); + + // delimiter_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── delimiter_loc:", 24); + pm_location_t *location = &cast->delimiter_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantPathOperatorWriteNode(", 30); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_operator_write_node_t *)node)->target); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_path_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_constant_path_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_path_operator_write_node_t *cast = (pm_constant_path_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantPathOperatorWriteNode (location: ", 43); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // target + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── target:", 17); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->target, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CONSTANT_PATH_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantPathOrWriteNode(", 24); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_or_write_node_t *)node)->target); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_path_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_path_or_write_node_t *cast = (pm_constant_path_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantPathOrWriteNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // target + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── target:", 17); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->target, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CONSTANT_PATH_TARGET_NODE: { - pm_buffer_append_str(buffer, "ConstantPathTargetNode(", 23); - if (((pm_constant_path_target_node_t *)node)->parent == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_target_node_t *)node)->parent); + pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantPathTargetNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // parent + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parent:", 17); + if (cast->parent == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parent, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // child + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── child:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->child, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_target_node_t *)node)->child); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_path_target_node_t *)node)->delimiter_loc); - pm_buffer_append_str(buffer, ")", 1); + + // delimiter_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── delimiter_loc:", 24); + pm_location_t *location = &cast->delimiter_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_CONSTANT_PATH_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantPathWriteNode(", 22); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_write_node_t *)node)->target); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_path_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_path_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_path_write_node_t *cast = (pm_constant_path_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantPathWriteNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // target + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── target:", 17); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->target, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_CONSTANT_READ_NODE: { - pm_buffer_append_str(buffer, "ConstantReadNode(", 17); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_constant_read_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_read_node_t *cast = (pm_constant_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantReadNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CONSTANT_TARGET_NODE: { - pm_buffer_append_str(buffer, "ConstantTargetNode(", 19); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_constant_target_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_target_node_t *cast = (pm_constant_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantTargetNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_CONSTANT_WRITE_NODE: { - pm_buffer_append_str(buffer, "ConstantWriteNode(", 18); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_constant_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_constant_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_constant_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_constant_write_node_t *cast = (pm_constant_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ConstantWriteNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_DEF_NODE: { - pm_buffer_append_str(buffer, "DefNode(", 8); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_def_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->receiver == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_def_node_t *)node)->receiver); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->parameters == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_def_node_t *)node)->parameters); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_def_node_t *)node)->body); - } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_def_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_def_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->def_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->operator_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->lparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->lparen_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->rparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->rparen_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->equal_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->equal_loc); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_def_node_t *)node)->end_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_def_node_t *)node)->end_keyword_loc); - } - pm_buffer_append_str(buffer, ")", 1); + pm_def_node_t *cast = (pm_def_node_t *) node; + pm_buffer_append_string(output_buffer, "@ DefNode (location: ", 21); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // parameters + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parameters:", 21); + if (cast->parameters == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parameters, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } + + // def_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── def_keyword_loc:", 26); + pm_location_t *location = &cast->def_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // equal_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── equal_loc:", 20); + pm_location_t *location = &cast->equal_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + break; } case PM_DEFINED_NODE: { - pm_buffer_append_str(buffer, "DefinedNode(", 12); - if (((pm_defined_node_t *)node)->lparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_defined_node_t *)node)->lparen_loc); + pm_defined_node_t *cast = (pm_defined_node_t *) node; + pm_buffer_append_string(output_buffer, "@ DefinedNode (location: ", 25); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_defined_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_defined_node_t *)node)->rparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_defined_node_t *)node)->rparen_loc); + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_defined_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_ELSE_NODE: { - pm_buffer_append_str(buffer, "ElseNode(", 9); - prettyprint_location(buffer, parser, &((pm_else_node_t *)node)->else_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_else_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_else_node_t *)node)->statements); + pm_else_node_t *cast = (pm_else_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ElseNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // else_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── else_keyword_loc:", 27); + pm_location_t *location = &cast->else_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_else_node_t *)node)->end_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_else_node_t *)node)->end_keyword_loc); + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_EMBEDDED_STATEMENTS_NODE: { - pm_buffer_append_str(buffer, "EmbeddedStatementsNode(", 23); - prettyprint_location(buffer, parser, &((pm_embedded_statements_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_embedded_statements_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_embedded_statements_node_t *)node)->statements); + pm_embedded_statements_node_t *cast = (pm_embedded_statements_node_t *) node; + pm_buffer_append_string(output_buffer, "@ EmbeddedStatementsNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_embedded_statements_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_EMBEDDED_VARIABLE_NODE: { - pm_buffer_append_str(buffer, "EmbeddedVariableNode(", 21); - prettyprint_location(buffer, parser, &((pm_embedded_variable_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_embedded_variable_node_t *)node)->variable); - pm_buffer_append_str(buffer, ")", 1); + pm_embedded_variable_node_t *cast = (pm_embedded_variable_node_t *) node; + pm_buffer_append_string(output_buffer, "@ EmbeddedVariableNode (location: ", 34); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // variable + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── variable:", 19); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->variable, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_ENSURE_NODE: { - pm_buffer_append_str(buffer, "EnsureNode(", 11); - prettyprint_location(buffer, parser, &((pm_ensure_node_t *)node)->ensure_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_ensure_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_ensure_node_t *)node)->statements); + pm_ensure_node_t *cast = (pm_ensure_node_t *) node; + pm_buffer_append_string(output_buffer, "@ EnsureNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // ensure_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── ensure_keyword_loc:", 29); + pm_location_t *location = &cast->ensure_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_ensure_node_t *)node)->end_keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_FALSE_NODE: { - pm_buffer_append_str(buffer, "FalseNode(", 10); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ FalseNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_FIND_PATTERN_NODE: { - pm_buffer_append_str(buffer, "FindPatternNode(", 16); - if (((pm_find_pattern_node_t *)node)->constant == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_find_pattern_node_t *)node)->constant); + pm_find_pattern_node_t *cast = (pm_find_pattern_node_t *) node; + pm_buffer_append_string(output_buffer, "@ FindPatternNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // constant + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── constant:", 19); + if (cast->constant == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->constant, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_find_pattern_node_t *)node)->left); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_find_pattern_node_t *)node)->requireds.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_find_pattern_node_t *) node)->requireds.nodes[index]); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_find_pattern_node_t *)node)->right); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_find_pattern_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_find_pattern_node_t *)node)->opening_loc); + + // requireds + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── requireds:", 20); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->requireds.size); + + size_t last_index = cast->requireds.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->requireds.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_find_pattern_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_find_pattern_node_t *)node)->closing_loc); + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── right:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ")", 1); - break; - } - case PM_FLIP_FLOP_NODE: { - pm_buffer_append_str(buffer, "FlipFlopNode(", 13); - if (((pm_flip_flop_node_t *)node)->left == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_flip_flop_node_t *)node)->left); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_flip_flop_node_t *)node)->right == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_flip_flop_node_t *)node)->right); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_flip_flop_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + break; } - case PM_FLOAT_NODE: { - pm_buffer_append_str(buffer, "FloatNode(", 10); - pm_buffer_append_str(buffer, ")", 1); + case PM_FLIP_FLOP_NODE: { + pm_flip_flop_node_t *cast = (pm_flip_flop_node_t *) node; + pm_buffer_append_string(output_buffer, "@ FlipFlopNode (location: ", 26); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + if (cast->left == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── right:", 16); + if (cast->right == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_RANGE_FLAGS_EXCLUDE_END) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " exclude_end", 12); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + break; + } + case PM_FLOAT_NODE: { + pm_buffer_append_string(output_buffer, "@ FloatNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_FOR_NODE: { - pm_buffer_append_str(buffer, "ForNode(", 8); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_for_node_t *)node)->index); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_for_node_t *)node)->collection); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_for_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_for_node_t *)node)->statements); + pm_for_node_t *cast = (pm_for_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ForNode (location: ", 21); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // index + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── index:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->index, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_for_node_t *)node)->for_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_for_node_t *)node)->in_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_for_node_t *)node)->do_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_for_node_t *)node)->do_keyword_loc); + + // collection + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── collection:", 21); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->collection, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // for_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── for_keyword_loc:", 26); + pm_location_t *location = &cast->for_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // in_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── in_keyword_loc:", 25); + pm_location_t *location = &cast->in_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_for_node_t *)node)->end_keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + + // do_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── do_keyword_loc:", 25); + pm_location_t *location = &cast->do_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_FORWARDING_ARGUMENTS_NODE: { - pm_buffer_append_str(buffer, "ForwardingArgumentsNode(", 24); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ ForwardingArgumentsNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_FORWARDING_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "ForwardingParameterNode(", 24); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ ForwardingParameterNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_FORWARDING_SUPER_NODE: { - pm_buffer_append_str(buffer, "ForwardingSuperNode(", 20); - if (((pm_forwarding_super_node_t *)node)->block == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_forwarding_super_node_t *)node)->block); + pm_forwarding_super_node_t *cast = (pm_forwarding_super_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ForwardingSuperNode (location: ", 33); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "GlobalVariableAndWriteNode(", 27); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_global_variable_and_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_and_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_global_variable_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_global_variable_and_write_node_t *cast = (pm_global_variable_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ GlobalVariableAndWriteNode (location: ", 40); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "GlobalVariableOperatorWriteNode(", 32); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_global_variable_operator_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_operator_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_global_variable_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_global_variable_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_global_variable_operator_write_node_t *cast = (pm_global_variable_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ GlobalVariableOperatorWriteNode (location: ", 45); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "GlobalVariableOrWriteNode(", 26); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_global_variable_or_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_or_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_global_variable_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_global_variable_or_write_node_t *cast = (pm_global_variable_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ GlobalVariableOrWriteNode (location: ", 39); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_GLOBAL_VARIABLE_READ_NODE: { - pm_buffer_append_str(buffer, "GlobalVariableReadNode(", 23); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_global_variable_read_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_global_variable_read_node_t *cast = (pm_global_variable_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ GlobalVariableReadNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_GLOBAL_VARIABLE_TARGET_NODE: { - pm_buffer_append_str(buffer, "GlobalVariableTargetNode(", 25); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_global_variable_target_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_global_variable_target_node_t *cast = (pm_global_variable_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ GlobalVariableTargetNode (location: ", 38); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_GLOBAL_VARIABLE_WRITE_NODE: { - pm_buffer_append_str(buffer, "GlobalVariableWriteNode(", 24); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_global_variable_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_global_variable_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_global_variable_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_global_variable_write_node_t *cast = (pm_global_variable_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ GlobalVariableWriteNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_HASH_NODE: { - pm_buffer_append_str(buffer, "HashNode(", 9); - prettyprint_location(buffer, parser, &((pm_hash_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_hash_node_t *)node)->elements.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_hash_node_t *) node)->elements.nodes[index]); + pm_hash_node_t *cast = (pm_hash_node_t *) node; + pm_buffer_append_string(output_buffer, "@ HashNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_hash_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + + // elements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── elements:", 19); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->elements.size); + + size_t last_index = cast->elements.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->elements.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_HASH_PATTERN_NODE: { - pm_buffer_append_str(buffer, "HashPatternNode(", 16); - if (((pm_hash_pattern_node_t *)node)->constant == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_hash_pattern_node_t *)node)->constant); + pm_hash_pattern_node_t *cast = (pm_hash_pattern_node_t *) node; + pm_buffer_append_string(output_buffer, "@ HashPatternNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // constant + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── constant:", 19); + if (cast->constant == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->constant, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_hash_pattern_node_t *)node)->assocs.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_hash_pattern_node_t *) node)->assocs.nodes[index]); + + // elements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── elements:", 19); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->elements.size); + + size_t last_index = cast->elements.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->elements.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_hash_pattern_node_t *)node)->kwrest == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_hash_pattern_node_t *)node)->kwrest); + + // rest + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rest:", 15); + if (cast->rest == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rest, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_hash_pattern_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_hash_pattern_node_t *)node)->opening_loc); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_hash_pattern_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_hash_pattern_node_t *)node)->closing_loc); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_IF_NODE: { - pm_buffer_append_str(buffer, "IfNode(", 7); - if (((pm_if_node_t *)node)->if_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_if_node_t *)node)->if_keyword_loc); + pm_if_node_t *cast = (pm_if_node_t *) node; + pm_buffer_append_string(output_buffer, "@ IfNode (location: ", 20); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // if_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── if_keyword_loc:", 25); + pm_location_t *location = &cast->if_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_if_node_t *)node)->predicate); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_if_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_if_node_t *)node)->statements); + + // predicate + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── predicate:", 20); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->predicate, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_if_node_t *)node)->consequent == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_if_node_t *)node)->consequent); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_if_node_t *)node)->end_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_if_node_t *)node)->end_keyword_loc); + + // consequent + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── consequent:", 21); + if (cast->consequent == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->consequent, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_IMAGINARY_NODE: { - pm_buffer_append_str(buffer, "ImaginaryNode(", 14); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_imaginary_node_t *)node)->numeric); - pm_buffer_append_str(buffer, ")", 1); + pm_imaginary_node_t *cast = (pm_imaginary_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ImaginaryNode (location: ", 27); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // numeric + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── numeric:", 18); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->numeric, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_IMPLICIT_NODE: { - pm_buffer_append_str(buffer, "ImplicitNode(", 13); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_implicit_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_implicit_node_t *cast = (pm_implicit_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ImplicitNode (location: ", 26); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_IN_NODE: { - pm_buffer_append_str(buffer, "InNode(", 7); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_in_node_t *)node)->pattern); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_in_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_in_node_t *)node)->statements); + pm_in_node_t *cast = (pm_in_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InNode (location: ", 20); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // pattern + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── pattern:", 18); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->pattern, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_in_node_t *)node)->in_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_in_node_t *)node)->then_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_in_node_t *)node)->then_loc); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // in_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── in_loc:", 17); + pm_location_t *location = &cast->in_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ")", 1); + + // then_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── then_loc:", 19); + pm_location_t *location = &cast->then_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + break; + } + case PM_INDEX_AND_WRITE_NODE: { + pm_index_and_write_node_t *cast = (pm_index_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ IndexAndWriteNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + break; + } + case PM_INDEX_OPERATOR_WRITE_NODE: { + pm_index_operator_write_node_t *cast = (pm_index_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ IndexOperatorWriteNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + break; + } + case PM_INDEX_OR_WRITE_NODE: { + pm_index_or_write_node_t *cast = (pm_index_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ IndexOrWriteNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // receiver + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── receiver:", 19); + if (cast->receiver == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->receiver, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // call_operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call_operator_loc:", 28); + pm_location_t *location = &cast->call_operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " safe_navigation", 16); + found = true; + } + if (cast->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " variable_call", 14); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "InstanceVariableAndWriteNode(", 29); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_instance_variable_and_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_and_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_instance_variable_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_instance_variable_and_write_node_t *cast = (pm_instance_variable_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InstanceVariableAndWriteNode (location: ", 42); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "InstanceVariableOperatorWriteNode(", 34); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_instance_variable_operator_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_operator_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_instance_variable_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_instance_variable_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_instance_variable_operator_write_node_t *cast = (pm_instance_variable_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InstanceVariableOperatorWriteNode (location: ", 47); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "InstanceVariableOrWriteNode(", 28); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_instance_variable_or_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_or_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_instance_variable_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_instance_variable_or_write_node_t *cast = (pm_instance_variable_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InstanceVariableOrWriteNode (location: ", 41); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_INSTANCE_VARIABLE_READ_NODE: { - pm_buffer_append_str(buffer, "InstanceVariableReadNode(", 25); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_instance_variable_read_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_instance_variable_read_node_t *cast = (pm_instance_variable_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InstanceVariableReadNode (location: ", 38); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_INSTANCE_VARIABLE_TARGET_NODE: { - pm_buffer_append_str(buffer, "InstanceVariableTargetNode(", 27); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_instance_variable_target_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_instance_variable_target_node_t *cast = (pm_instance_variable_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InstanceVariableTargetNode (location: ", 40); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_INSTANCE_VARIABLE_WRITE_NODE: { - pm_buffer_append_str(buffer, "InstanceVariableWriteNode(", 26); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_instance_variable_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_instance_variable_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_instance_variable_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_instance_variable_write_node_t *cast = (pm_instance_variable_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InstanceVariableWriteNode (location: ", 39); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_INTEGER_NODE: { - pm_buffer_append_str(buffer, "IntegerNode(", 12); - char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_integer_node_t *cast = (pm_integer_node_t *) node; + pm_buffer_append_string(output_buffer, "@ IntegerNode (location: ", 25); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_INTEGER_BASE_FLAGS_BINARY) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " binary", 7); + found = true; + } + if (cast->base.flags & PM_INTEGER_BASE_FLAGS_OCTAL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " octal", 6); + found = true; + } + if (cast->base.flags & PM_INTEGER_BASE_FLAGS_DECIMAL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " decimal", 8); + found = true; + } + if (cast->base.flags & PM_INTEGER_BASE_FLAGS_HEXADECIMAL) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " hexadecimal", 12); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: { - pm_buffer_append_str(buffer, "InterpolatedMatchLastLineNode(", 30); - prettyprint_location(buffer, parser, &((pm_interpolated_match_last_line_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_interpolated_match_last_line_node_t *)node)->parts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_interpolated_match_last_line_node_t *) node)->parts.nodes[index]); + pm_interpolated_match_last_line_node_t *cast = (pm_interpolated_match_last_line_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InterpolatedMatchLastLineNode (location: ", 43); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // parts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->parts.size); + + size_t last_index = cast->parts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ignore_case", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EXTENDED) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " extended", 9); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " multi_line", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ONCE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " once", 5); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " euc_jp", 7); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ascii_8bit", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " windows_31j", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " utf_8", 6); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + break; + } + case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { + pm_interpolated_regular_expression_node_t *cast = (pm_interpolated_regular_expression_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InterpolatedRegularExpressionNode (location: ", 47); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // parts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->parts.size); + + size_t last_index = cast->parts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_interpolated_match_last_line_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); - break; - } - case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { - pm_buffer_append_str(buffer, "InterpolatedRegularExpressionNode(", 34); - prettyprint_location(buffer, parser, &((pm_interpolated_regular_expression_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_interpolated_regular_expression_node_t *)node)->parts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_interpolated_regular_expression_node_t *) node)->parts.nodes[index]); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_interpolated_regular_expression_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ignore_case", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EXTENDED) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " extended", 9); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " multi_line", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ONCE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " once", 5); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " euc_jp", 7); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ascii_8bit", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " windows_31j", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " utf_8", 6); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_INTERPOLATED_STRING_NODE: { - pm_buffer_append_str(buffer, "InterpolatedStringNode(", 23); - if (((pm_interpolated_string_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_interpolated_string_node_t *)node)->opening_loc); + pm_interpolated_string_node_t *cast = (pm_interpolated_string_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InterpolatedStringNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_interpolated_string_node_t *)node)->parts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_interpolated_string_node_t *) node)->parts.nodes[index]); + + // parts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->parts.size); + + size_t last_index = cast->parts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_interpolated_string_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_interpolated_string_node_t *)node)->closing_loc); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_INTERPOLATED_SYMBOL_NODE: { - pm_buffer_append_str(buffer, "InterpolatedSymbolNode(", 23); - if (((pm_interpolated_symbol_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_interpolated_symbol_node_t *)node)->opening_loc); + pm_interpolated_symbol_node_t *cast = (pm_interpolated_symbol_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InterpolatedSymbolNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_interpolated_symbol_node_t *)node)->parts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_interpolated_symbol_node_t *) node)->parts.nodes[index]); + + // parts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->parts.size); + + size_t last_index = cast->parts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_interpolated_symbol_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_interpolated_symbol_node_t *)node)->closing_loc); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_INTERPOLATED_X_STRING_NODE: { - pm_buffer_append_str(buffer, "InterpolatedXStringNode(", 24); - prettyprint_location(buffer, parser, &((pm_interpolated_x_string_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_interpolated_x_string_node_t *)node)->parts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_interpolated_x_string_node_t *) node)->parts.nodes[index]); + pm_interpolated_x_string_node_t *cast = (pm_interpolated_x_string_node_t *) node; + pm_buffer_append_string(output_buffer, "@ InterpolatedXStringNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // parts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->parts.size); + + size_t last_index = cast->parts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_interpolated_x_string_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_KEYWORD_HASH_NODE: { - pm_buffer_append_str(buffer, "KeywordHashNode(", 16); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_keyword_hash_node_t *)node)->elements.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_keyword_hash_node_t *) node)->elements.nodes[index]); + pm_keyword_hash_node_t *cast = (pm_keyword_hash_node_t *) node; + pm_buffer_append_string(output_buffer, "@ KeywordHashNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // elements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── elements:", 19); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->elements.size); + + size_t last_index = cast->elements.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_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->elements.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_KEYWORD_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "KeywordParameterNode(", 21); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_keyword_parameter_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_keyword_parameter_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_keyword_parameter_node_t *)node)->value == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_keyword_parameter_node_t *)node)->value); + pm_keyword_parameter_node_t *cast = (pm_keyword_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ KeywordParameterNode (location: ", 34); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + if (cast->value == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_KEYWORD_REST_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "KeywordRestParameterNode(", 25); - if (((pm_keyword_rest_parameter_node_t *)node)->name == 0) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_keyword_rest_parameter_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); + pm_keyword_rest_parameter_node_t *cast = (pm_keyword_rest_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ KeywordRestParameterNode (location: ", 38); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + if (cast->name == 0) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_keyword_rest_parameter_node_t *)node)->name_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_keyword_rest_parameter_node_t *)node)->name_loc); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_keyword_rest_parameter_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_LAMBDA_NODE: { - pm_buffer_append_str(buffer, "LambdaNode(", 11); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_lambda_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_lambda_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_lambda_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_lambda_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_lambda_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_lambda_node_t *)node)->parameters == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_lambda_node_t *)node)->parameters); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_lambda_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_lambda_node_t *)node)->body); - } - pm_buffer_append_str(buffer, ")", 1); + pm_lambda_node_t *cast = (pm_lambda_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LambdaNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // parameters + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── parameters:", 21); + if (cast->parameters == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->parameters, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + break; } case PM_LOCAL_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_str(buffer, "LocalVariableAndWriteNode(", 26); - prettyprint_location(buffer, parser, &((pm_local_variable_and_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_local_variable_and_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_local_variable_and_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_local_variable_and_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((pm_local_variable_and_write_node_t *)node)->depth); - pm_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_local_variable_and_write_node_t *cast = (pm_local_variable_and_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LocalVariableAndWriteNode (location: ", 39); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // depth + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── depth:", 16); + pm_buffer_append_format(output_buffer, " %d\n", cast->depth); + } + break; } case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_str(buffer, "LocalVariableOperatorWriteNode(", 31); - prettyprint_location(buffer, parser, &((pm_local_variable_operator_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_local_variable_operator_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_local_variable_operator_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_local_variable_operator_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((pm_local_variable_operator_write_node_t *)node)->operator); - pm_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((pm_local_variable_operator_write_node_t *)node)->depth); - pm_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_local_variable_operator_write_node_t *cast = (pm_local_variable_operator_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LocalVariableOperatorWriteNode (location: ", 44); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // operator + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator:", 19); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->operator); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // depth + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── depth:", 16); + pm_buffer_append_format(output_buffer, " %d\n", cast->depth); + } + break; } case PM_LOCAL_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_str(buffer, "LocalVariableOrWriteNode(", 25); - prettyprint_location(buffer, parser, &((pm_local_variable_or_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_local_variable_or_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_local_variable_or_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_local_variable_or_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((pm_local_variable_or_write_node_t *)node)->depth); - pm_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_local_variable_or_write_node_t *cast = (pm_local_variable_or_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LocalVariableOrWriteNode (location: ", 38); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // depth + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── depth:", 16); + pm_buffer_append_format(output_buffer, " %d\n", cast->depth); + } + break; } case PM_LOCAL_VARIABLE_READ_NODE: { - pm_buffer_append_str(buffer, "LocalVariableReadNode(", 22); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_local_variable_read_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((pm_local_variable_read_node_t *)node)->depth); - pm_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LocalVariableReadNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // depth + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── depth:", 16); + pm_buffer_append_format(output_buffer, " %d\n", cast->depth); + } + break; } case PM_LOCAL_VARIABLE_TARGET_NODE: { - pm_buffer_append_str(buffer, "LocalVariableTargetNode(", 24); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_local_variable_target_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((pm_local_variable_target_node_t *)node)->depth); - pm_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LocalVariableTargetNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // depth + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── depth:", 16); + pm_buffer_append_format(output_buffer, " %d\n", cast->depth); + } + break; } case PM_LOCAL_VARIABLE_WRITE_NODE: { - pm_buffer_append_str(buffer, "LocalVariableWriteNode(", 23); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_local_variable_write_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((pm_local_variable_write_node_t *)node)->depth); - pm_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_local_variable_write_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_local_variable_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_local_variable_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_local_variable_write_node_t *cast = (pm_local_variable_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ LocalVariableWriteNode (location: ", 36); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // depth + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── depth:", 16); + pm_buffer_append_format(output_buffer, " %d\n", cast->depth); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_MATCH_LAST_LINE_NODE: { - pm_buffer_append_str(buffer, "MatchLastLineNode(", 18); - prettyprint_location(buffer, parser, &((pm_match_last_line_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_match_last_line_node_t *)node)->content_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_match_last_line_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_bytes(buffer, pm_string_source(&((pm_match_last_line_node_t *)node)->unescaped), pm_string_length(&((pm_match_last_line_node_t *)node)->unescaped)); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_match_last_line_node_t *cast = (pm_match_last_line_node_t *) node; + pm_buffer_append_string(output_buffer, "@ MatchLastLineNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // content_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── content_loc:", 22); + pm_location_t *location = &cast->content_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // unescaped + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── unescaped:", 20); + pm_buffer_append_string(output_buffer, " \"", 2); + prettyprint_source(output_buffer, pm_string_source(&cast->unescaped), pm_string_length(&cast->unescaped)); + pm_buffer_append_string(output_buffer, "\"\n", 2); + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ignore_case", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EXTENDED) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " extended", 9); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " multi_line", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ONCE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " once", 5); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " euc_jp", 7); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ascii_8bit", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " windows_31j", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " utf_8", 6); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_MATCH_PREDICATE_NODE: { - pm_buffer_append_str(buffer, "MatchPredicateNode(", 19); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_match_predicate_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_match_predicate_node_t *)node)->pattern); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_match_predicate_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_match_predicate_node_t *cast = (pm_match_predicate_node_t *) node; + pm_buffer_append_string(output_buffer, "@ MatchPredicateNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // pattern + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── pattern:", 18); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->pattern, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_MATCH_REQUIRED_NODE: { - pm_buffer_append_str(buffer, "MatchRequiredNode(", 18); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_match_required_node_t *)node)->value); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_match_required_node_t *)node)->pattern); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_match_required_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_match_required_node_t *cast = (pm_match_required_node_t *) node; + pm_buffer_append_string(output_buffer, "@ MatchRequiredNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // pattern + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── pattern:", 18); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->pattern, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_MATCH_WRITE_NODE: { - pm_buffer_append_str(buffer, "MatchWriteNode(", 15); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_match_write_node_t *)node)->call); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_match_write_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_match_write_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); + pm_match_write_node_t *cast = (pm_match_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ MatchWriteNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // call + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── call:", 15); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->call, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_MISSING_NODE: { - pm_buffer_append_str(buffer, "MissingNode(", 12); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ MissingNode (location: ", 25); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_MODULE_NODE: { - pm_buffer_append_str(buffer, "ModuleNode(", 11); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_module_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_module_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_module_node_t *)node)->module_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_module_node_t *)node)->constant_path); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_module_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_module_node_t *)node)->body); - } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_module_node_t *)node)->end_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_module_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_module_node_t *cast = (pm_module_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ModuleNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } + + // module_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── module_keyword_loc:", 29); + pm_location_t *location = &cast->module_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // constant_path + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── constant_path:", 24); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->constant_path, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_MULTI_TARGET_NODE: { - pm_buffer_append_str(buffer, "MultiTargetNode(", 16); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_multi_target_node_t *)node)->targets.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_multi_target_node_t *) node)->targets.nodes[index]); + pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node; + pm_buffer_append_string(output_buffer, "@ MultiTargetNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // lefts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lefts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->lefts.size); + + size_t last_index = cast->lefts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->lefts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_multi_target_node_t *)node)->lparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_multi_target_node_t *)node)->lparen_loc); + + // rest + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rest:", 15); + if (cast->rest == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rest, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // rights + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rights:", 17); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->rights.size); + + size_t last_index = cast->rights.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rights.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_multi_target_node_t *)node)->rparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_multi_target_node_t *)node)->rparen_loc); + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_MULTI_WRITE_NODE: { - pm_buffer_append_str(buffer, "MultiWriteNode(", 15); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_multi_write_node_t *)node)->targets.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_multi_write_node_t *) node)->targets.nodes[index]); + pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node; + pm_buffer_append_string(output_buffer, "@ MultiWriteNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // lefts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lefts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->lefts.size); + + size_t last_index = cast->lefts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->lefts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // rest + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rest:", 15); + if (cast->rest == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rest, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // rights + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rights:", 17); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->rights.size); + + size_t last_index = cast->rights.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rights.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_multi_write_node_t *)node)->lparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_multi_write_node_t *)node)->lparen_loc); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_multi_write_node_t *)node)->rparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_multi_write_node_t *)node)->rparen_loc); + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_multi_write_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_multi_write_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_NEXT_NODE: { - pm_buffer_append_str(buffer, "NextNode(", 9); - if (((pm_next_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_next_node_t *)node)->arguments); + pm_next_node_t *cast = (pm_next_node_t *) node; + pm_buffer_append_string(output_buffer, "@ NextNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_next_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_NIL_NODE: { - pm_buffer_append_str(buffer, "NilNode(", 8); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ NilNode (location: ", 21); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_NO_KEYWORDS_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "NoKeywordsParameterNode(", 24); - prettyprint_location(buffer, parser, &((pm_no_keywords_parameter_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_no_keywords_parameter_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_no_keywords_parameter_node_t *cast = (pm_no_keywords_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ NoKeywordsParameterNode (location: ", 37); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_NUMBERED_REFERENCE_READ_NODE: { - pm_buffer_append_str(buffer, "NumberedReferenceReadNode(", 26); - char number_buffer[12]; - snprintf(number_buffer, sizeof(number_buffer), "+%d", ((pm_numbered_reference_read_node_t *)node)->number); - pm_buffer_append_str(buffer, number_buffer, strlen(number_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_numbered_reference_read_node_t *cast = (pm_numbered_reference_read_node_t *) node; + pm_buffer_append_string(output_buffer, "@ NumberedReferenceReadNode (location: ", 39); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // number + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── number:", 17); + pm_buffer_append_format(output_buffer, " %d\n", cast->number); + } + break; } case PM_OPTIONAL_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "OptionalParameterNode(", 22); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_optional_parameter_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_optional_parameter_node_t *)node)->name_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_optional_parameter_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_optional_parameter_node_t *)node)->value); - pm_buffer_append_str(buffer, ")", 1); + pm_optional_parameter_node_t *cast = (pm_optional_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ OptionalParameterNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // value + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── value:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->value, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_OR_NODE: { - pm_buffer_append_str(buffer, "OrNode(", 7); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_or_node_t *)node)->left); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_or_node_t *)node)->right); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_or_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_or_node_t *cast = (pm_or_node_t *) node; + pm_buffer_append_string(output_buffer, "@ OrNode (location: ", 20); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── right:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_PARAMETERS_NODE: { - pm_buffer_append_str(buffer, "ParametersNode(", 15); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_parameters_node_t *)node)->requireds.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_parameters_node_t *) node)->requireds.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_parameters_node_t *)node)->optionals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_parameters_node_t *) node)->optionals.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_parameters_node_t *)node)->rest == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_parameters_node_t *)node)->rest); - } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_parameters_node_t *)node)->posts.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_parameters_node_t *) node)->posts.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_parameters_node_t *)node)->keywords.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_parameters_node_t *) node)->keywords.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_parameters_node_t *)node)->keyword_rest == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_parameters_node_t *)node)->keyword_rest); - } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_parameters_node_t *)node)->block == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_parameters_node_t *)node)->block); - } - pm_buffer_append_str(buffer, ")", 1); + pm_parameters_node_t *cast = (pm_parameters_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ParametersNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // requireds + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── requireds:", 20); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->requireds.size); + + size_t last_index = cast->requireds.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->requireds.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // optionals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── optionals:", 20); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->optionals.size); + + size_t last_index = cast->optionals.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->optionals.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // rest + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rest:", 15); + if (cast->rest == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rest, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // posts + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── posts:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->posts.size); + + size_t last_index = cast->posts.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->posts.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // keywords + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keywords:", 19); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->keywords.size); + + size_t last_index = cast->keywords.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->keywords.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // keyword_rest + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_rest:", 23); + if (cast->keyword_rest == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->keyword_rest, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + break; } case PM_PARENTHESES_NODE: { - pm_buffer_append_str(buffer, "ParenthesesNode(", 16); - if (((pm_parentheses_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_parentheses_node_t *)node)->body); + pm_parentheses_node_t *cast = (pm_parentheses_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ParenthesesNode (location: ", 29); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_parentheses_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_parentheses_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_PINNED_EXPRESSION_NODE: { - pm_buffer_append_str(buffer, "PinnedExpressionNode(", 21); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_pinned_expression_node_t *)node)->expression); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pinned_expression_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pinned_expression_node_t *)node)->lparen_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pinned_expression_node_t *)node)->rparen_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_pinned_expression_node_t *cast = (pm_pinned_expression_node_t *) node; + pm_buffer_append_string(output_buffer, "@ PinnedExpressionNode (location: ", 34); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // expression + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── expression:", 21); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->expression, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_PINNED_VARIABLE_NODE: { - pm_buffer_append_str(buffer, "PinnedVariableNode(", 19); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_pinned_variable_node_t *)node)->variable); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pinned_variable_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_pinned_variable_node_t *cast = (pm_pinned_variable_node_t *) node; + pm_buffer_append_string(output_buffer, "@ PinnedVariableNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // variable + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── variable:", 19); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->variable, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_POST_EXECUTION_NODE: { - pm_buffer_append_str(buffer, "PostExecutionNode(", 18); - if (((pm_post_execution_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_post_execution_node_t *)node)->statements); + pm_post_execution_node_t *cast = (pm_post_execution_node_t *) node; + pm_buffer_append_string(output_buffer, "@ PostExecutionNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_post_execution_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_post_execution_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_post_execution_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_PRE_EXECUTION_NODE: { - pm_buffer_append_str(buffer, "PreExecutionNode(", 17); - if (((pm_pre_execution_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_pre_execution_node_t *)node)->statements); + pm_pre_execution_node_t *cast = (pm_pre_execution_node_t *) node; + pm_buffer_append_string(output_buffer, "@ PreExecutionNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pre_execution_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pre_execution_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_pre_execution_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_PROGRAM_NODE: { - pm_buffer_append_str(buffer, "ProgramNode(", 12); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_program_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_program_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); + pm_program_node_t *cast = (pm_program_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ProgramNode (location: ", 25); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_program_node_t *)node)->statements); - pm_buffer_append_str(buffer, ")", 1); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── statements:", 21); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_RANGE_NODE: { - pm_buffer_append_str(buffer, "RangeNode(", 10); - if (((pm_range_node_t *)node)->left == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_range_node_t *)node)->left); + pm_range_node_t *cast = (pm_range_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RangeNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + if (cast->left == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── right:", 16); + if (cast->right == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_range_node_t *)node)->right == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_range_node_t *)node)->right); + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_RANGE_FLAGS_EXCLUDE_END) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " exclude_end", 12); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_range_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_RATIONAL_NODE: { - pm_buffer_append_str(buffer, "RationalNode(", 13); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_rational_node_t *)node)->numeric); - pm_buffer_append_str(buffer, ")", 1); + pm_rational_node_t *cast = (pm_rational_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RationalNode (location: ", 26); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // numeric + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── numeric:", 18); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->numeric, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_REDO_NODE: { - pm_buffer_append_str(buffer, "RedoNode(", 9); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ RedoNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_REGULAR_EXPRESSION_NODE: { - pm_buffer_append_str(buffer, "RegularExpressionNode(", 22); - prettyprint_location(buffer, parser, &((pm_regular_expression_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_regular_expression_node_t *)node)->content_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_regular_expression_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_bytes(buffer, pm_string_source(&((pm_regular_expression_node_t *)node)->unescaped), pm_string_length(&((pm_regular_expression_node_t *)node)->unescaped)); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); - break; - } - case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "RequiredDestructuredParameterNode(", 34); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_required_destructured_parameter_node_t *)node)->parameters.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_required_destructured_parameter_node_t *) node)->parameters.nodes[index]); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_required_destructured_parameter_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_required_destructured_parameter_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_regular_expression_node_t *cast = (pm_regular_expression_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RegularExpressionNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // content_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── content_loc:", 22); + pm_location_t *location = &cast->content_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // unescaped + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── unescaped:", 20); + pm_buffer_append_string(output_buffer, " \"", 2); + prettyprint_source(output_buffer, pm_string_source(&cast->unescaped), pm_string_length(&cast->unescaped)); + pm_buffer_append_string(output_buffer, "\"\n", 2); + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ignore_case", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EXTENDED) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " extended", 9); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " multi_line", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ONCE) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " once", 5); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " euc_jp", 7); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " ascii_8bit", 11); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " windows_31j", 12); + found = true; + } + if (cast->base.flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " utf_8", 6); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_REQUIRED_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "RequiredParameterNode(", 22); - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_required_parameter_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); - pm_buffer_append_str(buffer, ")", 1); + pm_required_parameter_node_t *cast = (pm_required_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RequiredParameterNode (location: ", 35); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── name:", 15); + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } + break; } case PM_RESCUE_MODIFIER_NODE: { - pm_buffer_append_str(buffer, "RescueModifierNode(", 19); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_rescue_modifier_node_t *)node)->expression); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_rescue_modifier_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_rescue_modifier_node_t *)node)->rescue_expression); - pm_buffer_append_str(buffer, ")", 1); + pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RescueModifierNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // expression + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── expression:", 21); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->expression, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // rescue_expression + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── rescue_expression:", 28); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->rescue_expression, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_RESCUE_NODE: { - pm_buffer_append_str(buffer, "RescueNode(", 11); - prettyprint_location(buffer, parser, &((pm_rescue_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_rescue_node_t *)node)->exceptions.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_rescue_node_t *) node)->exceptions.nodes[index]); + pm_rescue_node_t *cast = (pm_rescue_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RescueNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // exceptions + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── exceptions:", 21); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->exceptions.size); + + size_t last_index = cast->exceptions.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->exceptions.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_rescue_node_t *)node)->operator_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_rescue_node_t *)node)->operator_loc); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_rescue_node_t *)node)->reference == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_rescue_node_t *)node)->reference); + + // reference + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── reference:", 20); + if (cast->reference == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->reference, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_rescue_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_rescue_node_t *)node)->statements); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_rescue_node_t *)node)->consequent == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_rescue_node_t *)node)->consequent); + + // consequent + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── consequent:", 21); + if (cast->consequent == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->consequent, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_REST_PARAMETER_NODE: { - pm_buffer_append_str(buffer, "RestParameterNode(", 18); - if (((pm_rest_parameter_node_t *)node)->name == 0) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - char name_buffer[12]; - snprintf(name_buffer, sizeof(name_buffer), "%u", ((pm_rest_parameter_node_t *)node)->name); - pm_buffer_append_str(buffer, name_buffer, strlen(name_buffer)); + pm_rest_parameter_node_t *cast = (pm_rest_parameter_node_t *) node; + pm_buffer_append_string(output_buffer, "@ RestParameterNode (location: ", 31); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // name + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name:", 15); + if (cast->name == 0) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + prettyprint_constant(output_buffer, parser, cast->name); + pm_buffer_append_byte(output_buffer, '\n'); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_rest_parameter_node_t *)node)->name_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_rest_parameter_node_t *)node)->name_loc); + + // name_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── name_loc:", 19); + pm_location_t *location = &cast->name_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_rest_parameter_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_RETRY_NODE: { - pm_buffer_append_str(buffer, "RetryNode(", 10); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ RetryNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_RETURN_NODE: { - pm_buffer_append_str(buffer, "ReturnNode(", 11); - prettyprint_location(buffer, parser, &((pm_return_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_return_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_return_node_t *)node)->arguments); + pm_return_node_t *cast = (pm_return_node_t *) node; + pm_buffer_append_string(output_buffer, "@ ReturnNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_SELF_NODE: { - pm_buffer_append_str(buffer, "SelfNode(", 9); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ SelfNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_SINGLETON_CLASS_NODE: { - pm_buffer_append_str(buffer, "SingletonClassNode(", 19); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_singleton_class_node_t *)node)->locals.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - char locals_buffer[12]; - snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((pm_singleton_class_node_t *)node)->locals.ids[index]); - pm_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); - } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_singleton_class_node_t *)node)->class_keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_singleton_class_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_singleton_class_node_t *)node)->expression); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_singleton_class_node_t *)node)->body == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_singleton_class_node_t *)node)->body); - } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_singleton_class_node_t *)node)->end_keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + pm_singleton_class_node_t *cast = (pm_singleton_class_node_t *) node; + pm_buffer_append_string(output_buffer, "@ SingletonClassNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // locals + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── locals:", 17); + pm_buffer_append_string(output_buffer, " [", 2); + for (uint32_t index = 0; index < cast->locals.size; index++) { + if (index != 0) pm_buffer_append_string(output_buffer, ", ", 2); + prettyprint_constant(output_buffer, parser, cast->locals.ids[index]); + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } + + // class_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── class_keyword_loc:", 28); + pm_location_t *location = &cast->class_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // expression + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── expression:", 21); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->expression, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── body:", 15); + if (cast->body == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + break; } case PM_SOURCE_ENCODING_NODE: { - pm_buffer_append_str(buffer, "SourceEncodingNode(", 19); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ SourceEncodingNode (location: ", 32); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_SOURCE_FILE_NODE: { - pm_buffer_append_str(buffer, "SourceFileNode(", 15); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_bytes(buffer, pm_string_source(&((pm_source_file_node_t *)node)->filepath), pm_string_length(&((pm_source_file_node_t *)node)->filepath)); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_str(buffer, ")", 1); + pm_source_file_node_t *cast = (pm_source_file_node_t *) node; + pm_buffer_append_string(output_buffer, "@ SourceFileNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // filepath + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── filepath:", 19); + pm_buffer_append_string(output_buffer, " \"", 2); + prettyprint_source(output_buffer, pm_string_source(&cast->filepath), pm_string_length(&cast->filepath)); + pm_buffer_append_string(output_buffer, "\"\n", 2); + } + break; } case PM_SOURCE_LINE_NODE: { - pm_buffer_append_str(buffer, "SourceLineNode(", 15); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ SourceLineNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_SPLAT_NODE: { - pm_buffer_append_str(buffer, "SplatNode(", 10); - prettyprint_location(buffer, parser, &((pm_splat_node_t *)node)->operator_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_splat_node_t *)node)->expression == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_splat_node_t *)node)->expression); + pm_splat_node_t *cast = (pm_splat_node_t *) node; + pm_buffer_append_string(output_buffer, "@ SplatNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // operator_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── operator_loc:", 23); + pm_location_t *location = &cast->operator_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ")", 1); + + // expression + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── expression:", 21); + if (cast->expression == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->expression, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + break; } case PM_STATEMENTS_NODE: { - pm_buffer_append_str(buffer, "StatementsNode(", 15); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_statements_node_t *)node)->body.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_statements_node_t *) node)->body.nodes[index]); + pm_statements_node_t *cast = (pm_statements_node_t *) node; + pm_buffer_append_string(output_buffer, "@ StatementsNode (location: ", 28); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // body + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── body:", 15); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->body.size); + + size_t last_index = cast->body.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_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->body.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_STRING_CONCAT_NODE: { - pm_buffer_append_str(buffer, "StringConcatNode(", 17); - prettyprint_node(buffer, parser, (pm_node_t *)((pm_string_concat_node_t *)node)->left); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_string_concat_node_t *)node)->right); - pm_buffer_append_str(buffer, ")", 1); + pm_string_concat_node_t *cast = (pm_string_concat_node_t *) node; + pm_buffer_append_string(output_buffer, "@ StringConcatNode (location: ", 30); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // left + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── left:", 15); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->left, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // right + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── right:", 16); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->right, prefix_buffer); + prefix_buffer->length = prefix_length; + } + break; } case PM_STRING_NODE: { - pm_buffer_append_str(buffer, "StringNode(", 11); - char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_string_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_string_node_t *)node)->opening_loc); - } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_string_node_t *)node)->content_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_string_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_string_node_t *)node)->closing_loc); - } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_bytes(buffer, pm_string_source(&((pm_string_node_t *)node)->unescaped), pm_string_length(&((pm_string_node_t *)node)->unescaped)); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_str(buffer, ")", 1); + pm_string_node_t *cast = (pm_string_node_t *) node; + pm_buffer_append_string(output_buffer, "@ StringNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── flags:", 16); + bool found = false; + if (cast->base.flags & PM_STRING_FLAGS_FROZEN) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " frozen", 7); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); + } + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // content_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── content_loc:", 22); + pm_location_t *location = &cast->content_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // unescaped + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── unescaped:", 20); + pm_buffer_append_string(output_buffer, " \"", 2); + prettyprint_source(output_buffer, pm_string_source(&cast->unescaped), pm_string_length(&cast->unescaped)); + pm_buffer_append_string(output_buffer, "\"\n", 2); + } + break; } case PM_SUPER_NODE: { - pm_buffer_append_str(buffer, "SuperNode(", 10); - prettyprint_location(buffer, parser, &((pm_super_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_super_node_t *)node)->lparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_super_node_t *)node)->lparen_loc); + pm_super_node_t *cast = (pm_super_node_t *) node; + pm_buffer_append_string(output_buffer, "@ SuperNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_super_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_super_node_t *)node)->arguments); + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_super_node_t *)node)->rparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_super_node_t *)node)->rparen_loc); + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_super_node_t *)node)->block == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_super_node_t *)node)->block); + + // block + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── block:", 16); + if (cast->block == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->block, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_SYMBOL_NODE: { - pm_buffer_append_str(buffer, "SymbolNode(", 11); - if (((pm_symbol_node_t *)node)->opening_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_symbol_node_t *)node)->opening_loc); + pm_symbol_node_t *cast = (pm_symbol_node_t *) node; + pm_buffer_append_string(output_buffer, "@ SymbolNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // value_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── value_loc:", 20); + pm_location_t *location = &cast->value_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_symbol_node_t *)node)->value_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_symbol_node_t *)node)->value_loc); + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_symbol_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_symbol_node_t *)node)->closing_loc); + + // unescaped + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── unescaped:", 20); + pm_buffer_append_string(output_buffer, " \"", 2); + prettyprint_source(output_buffer, pm_string_source(&cast->unescaped), pm_string_length(&cast->unescaped)); + pm_buffer_append_string(output_buffer, "\"\n", 2); } - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_bytes(buffer, pm_string_source(&((pm_symbol_node_t *)node)->unescaped), pm_string_length(&((pm_symbol_node_t *)node)->unescaped)); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_TRUE_NODE: { - pm_buffer_append_str(buffer, "TrueNode(", 9); - pm_buffer_append_str(buffer, ")", 1); + pm_buffer_append_string(output_buffer, "@ TrueNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + break; } case PM_UNDEF_NODE: { - pm_buffer_append_str(buffer, "UndefNode(", 10); - pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_undef_node_t *)node)->names.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_undef_node_t *) node)->names.nodes[index]); + pm_undef_node_t *cast = (pm_undef_node_t *) node; + pm_buffer_append_string(output_buffer, "@ UndefNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // names + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── names:", 16); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->names.size); + + size_t last_index = cast->names.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->names.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_undef_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_UNLESS_NODE: { - pm_buffer_append_str(buffer, "UnlessNode(", 11); - prettyprint_location(buffer, parser, &((pm_unless_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_unless_node_t *)node)->predicate); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_unless_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_unless_node_t *)node)->statements); + pm_unless_node_t *cast = (pm_unless_node_t *) node; + pm_buffer_append_string(output_buffer, "@ UnlessNode (location: ", 24); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // predicate + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── predicate:", 20); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->predicate, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_unless_node_t *)node)->consequent == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_unless_node_t *)node)->consequent); + + // consequent + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── consequent:", 21); + if (cast->consequent == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->consequent, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_unless_node_t *)node)->end_keyword_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_unless_node_t *)node)->end_keyword_loc); + + // end_keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── end_keyword_loc:", 26); + pm_location_t *location = &cast->end_keyword_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_UNTIL_NODE: { - pm_buffer_append_str(buffer, "UntilNode(", 10); - prettyprint_location(buffer, parser, &((pm_until_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_until_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_until_node_t *)node)->closing_loc); + pm_until_node_t *cast = (pm_until_node_t *) node; + pm_buffer_append_string(output_buffer, "@ UntilNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_until_node_t *)node)->predicate); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_until_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_until_node_t *)node)->statements); + + // predicate + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── predicate:", 20); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->predicate, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } + } + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_LOOP_FLAGS_BEGIN_MODIFIER) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " begin_modifier", 15); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); } - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_WHEN_NODE: { - pm_buffer_append_str(buffer, "WhenNode(", 9); - prettyprint_location(buffer, parser, &((pm_when_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "[", 1); - for (uint32_t index = 0; index < ((pm_when_node_t *)node)->conditions.size; index++) { - if (index != 0) pm_buffer_append_str(buffer, ", ", 2); - prettyprint_node(buffer, parser, (pm_node_t *) ((pm_when_node_t *) node)->conditions.nodes[index]); + pm_when_node_t *cast = (pm_when_node_t *) node; + pm_buffer_append_string(output_buffer, "@ WhenNode (location: ", 22); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // conditions + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── conditions:", 21); + pm_buffer_append_format(output_buffer, " (length: %d)\n", cast->conditions.size); + + size_t last_index = cast->conditions.size; + for (uint32_t index = 0; index < last_index; index++) { + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + + if (index == last_index - 1) { + pm_buffer_append_string(output_buffer, "└── ", 10); + pm_buffer_append_string(prefix_buffer, " ", 4); + } else { + pm_buffer_append_string(output_buffer, "├── ", 10); + pm_buffer_append_string(prefix_buffer, "│ ", 6); + } + + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->conditions.nodes[index], prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, "]", 1); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_when_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_when_node_t *)node)->statements); + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, " ", 4); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_WHILE_NODE: { - pm_buffer_append_str(buffer, "WhileNode(", 10); - prettyprint_location(buffer, parser, &((pm_while_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_while_node_t *)node)->closing_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_while_node_t *)node)->closing_loc); + pm_while_node_t *cast = (pm_while_node_t *) node; + pm_buffer_append_string(output_buffer, "@ WhileNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + } + + // predicate + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── predicate:", 20); + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->predicate, prefix_buffer); + prefix_buffer->length = prefix_length; + } + + // statements + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── statements:", 21); + if (cast->statements == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->statements, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (pm_node_t *)((pm_while_node_t *)node)->predicate); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_while_node_t *)node)->statements == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_while_node_t *)node)->statements); + + // flags + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── flags:", 16); + bool found = false; + if (cast->base.flags & PM_LOOP_FLAGS_BEGIN_MODIFIER) { + if (found) pm_buffer_append_byte(output_buffer, ','); + pm_buffer_append_string(output_buffer, " begin_modifier", 15); + found = true; + } + if (!found) pm_buffer_append_string(output_buffer, " ∅", 4); + pm_buffer_append_byte(output_buffer, '\n'); } - pm_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - snprintf(flags_buffer, sizeof(flags_buffer), "+%d", (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); - pm_buffer_append_str(buffer, ")", 1); + break; } case PM_X_STRING_NODE: { - pm_buffer_append_str(buffer, "XStringNode(", 12); - prettyprint_location(buffer, parser, &((pm_x_string_node_t *)node)->opening_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_x_string_node_t *)node)->content_loc); - pm_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((pm_x_string_node_t *)node)->closing_loc); - pm_buffer_append_str(buffer, ", ", 2); pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_bytes(buffer, pm_string_source(&((pm_x_string_node_t *)node)->unescaped), pm_string_length(&((pm_x_string_node_t *)node)->unescaped)); - pm_buffer_append_str(buffer, "\"", 1); - pm_buffer_append_str(buffer, ")", 1); + pm_x_string_node_t *cast = (pm_x_string_node_t *) node; + pm_buffer_append_string(output_buffer, "@ XStringNode (location: ", 25); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // opening_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── opening_loc:", 22); + pm_location_t *location = &cast->opening_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // content_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── content_loc:", 22); + pm_location_t *location = &cast->content_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // closing_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── closing_loc:", 22); + pm_location_t *location = &cast->closing_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // unescaped + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── unescaped:", 20); + pm_buffer_append_string(output_buffer, " \"", 2); + prettyprint_source(output_buffer, pm_string_source(&cast->unescaped), pm_string_length(&cast->unescaped)); + pm_buffer_append_string(output_buffer, "\"\n", 2); + } + break; } case PM_YIELD_NODE: { - pm_buffer_append_str(buffer, "YieldNode(", 10); - prettyprint_location(buffer, parser, &((pm_yield_node_t *)node)->keyword_loc); - pm_buffer_append_str(buffer, ", ", 2); if (((pm_yield_node_t *)node)->lparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_yield_node_t *)node)->lparen_loc); + pm_yield_node_t *cast = (pm_yield_node_t *) node; + pm_buffer_append_string(output_buffer, "@ YieldNode (location: ", 23); + prettyprint_location(output_buffer, parser, &node->location); + pm_buffer_append_string(output_buffer, ")\n", 2); + + // keyword_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── keyword_loc:", 22); + pm_location_t *location = &cast->keyword_loc; + pm_buffer_append_byte(output_buffer, ' '); + 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); + } + + // lparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── lparen_loc:", 21); + pm_location_t *location = &cast->lparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_yield_node_t *)node)->arguments == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_node(buffer, parser, (pm_node_t *)((pm_yield_node_t *)node)->arguments); + + // arguments + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "├── arguments:", 20); + if (cast->arguments == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, '\n'); + + size_t prefix_length = prefix_buffer->length; + pm_buffer_append_string(prefix_buffer, "│ ", 6); + pm_buffer_concat(output_buffer, prefix_buffer); + prettyprint_node(output_buffer, parser, (pm_node_t *) cast->arguments, prefix_buffer); + prefix_buffer->length = prefix_length; + } } - pm_buffer_append_str(buffer, ", ", 2); if (((pm_yield_node_t *)node)->rparen_loc.start == NULL) { - pm_buffer_append_str(buffer, "nil", 3); - } else { - prettyprint_location(buffer, parser, &((pm_yield_node_t *)node)->rparen_loc); + + // rparen_loc + { + pm_buffer_concat(output_buffer, prefix_buffer); + pm_buffer_append_string(output_buffer, "└── rparen_loc:", 21); + pm_location_t *location = &cast->rparen_loc; + if (location->start == NULL) { + pm_buffer_append_string(output_buffer, " ∅\n", 5); + } else { + pm_buffer_append_byte(output_buffer, ' '); + 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); + } } - pm_buffer_append_str(buffer, ")", 1); + break; } } } -void -pm_print_node(pm_parser_t *parser, pm_node_t *node) { - pm_buffer_t buffer; - if (!pm_buffer_init(&buffer)) return; - - prettyprint_node(&buffer, parser, node); - printf("%.*s\n", (int) buffer.length, buffer.value); - - pm_buffer_free(&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 *buffer) { - prettyprint_node(buffer, parser, node); +pm_prettyprint(pm_buffer_t *output_buffer, const 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/src/main/c/yarp/src/prism.c b/src/main/c/yarp/src/prism.c index 0fc993377c34..17d6fb62999e 100644 --- a/src/main/c/yarp/src/prism.c +++ b/src/main/c/yarp/src/prism.c @@ -40,6 +40,7 @@ debug_context(pm_context_t context) { case PM_CONTEXT_BLOCK_BRACES: return "BLOCK_BRACES"; case PM_CONTEXT_BLOCK_KEYWORDS: return "BLOCK_KEYWORDS"; case PM_CONTEXT_FOR: return "FOR"; + case PM_CONTEXT_FOR_INDEX: return "FOR_INDEX"; case PM_CONTEXT_IF: return "IF"; case PM_CONTEXT_MAIN: return "MAIN"; case PM_CONTEXT_MODULE: return "MODULE"; @@ -80,14 +81,12 @@ debug_contexts(pm_parser_t *parser) { } PRISM_ATTRIBUTE_UNUSED static void -debug_node(const char *message, pm_parser_t *parser, pm_node_t *node) { - pm_buffer_t buffer; - if (!pm_buffer_init(&buffer)) return; - - pm_prettyprint(parser, node, &buffer); +debug_node(const pm_parser_t *parser, const pm_node_t *node) { + pm_buffer_t output_buffer = { 0 }; + pm_prettyprint(&output_buffer, parser, node); - fprintf(stderr, "%s\n%.*s\n", message, (int) buffer.length, buffer.value); - pm_buffer_free(&buffer); + fprintf(stderr, "%.*s", (int) output_buffer.length, output_buffer.value); + pm_buffer_free(&output_buffer); } PRISM_ATTRIBUTE_UNUSED static void @@ -496,18 +495,8 @@ pm_parser_constant_id_owned(pm_parser_t *parser, const uint8_t *start, size_t le // Retrieve the constant pool id for the given static literal C string. static inline pm_constant_id_t -pm_parser_constant_id_static(pm_parser_t *parser, const char *start, size_t length) { - uint8_t *owned_copy; - if (length > 0) { - owned_copy = malloc(length); - memcpy(owned_copy, start, length); - } else { - owned_copy = malloc(1); - owned_copy[0] = '\0'; - } - return pm_constant_pool_insert_owned(&parser->constant_pool, owned_copy, length); - // Does not work because the static literal cannot be serialized as an offset of source - // return pm_constant_pool_insert_shared(&parser->constant_pool, start, length); +pm_parser_constant_id_constant(pm_parser_t *parser, const char *start, size_t length) { + return pm_constant_pool_insert_constant(&parser->constant_pool, (const uint8_t *) start, length); } // Retrieve the constant pool id for the given token. @@ -658,87 +647,6 @@ pm_arguments_validate_block(pm_parser_t *parser, pm_arguments_t *arguments, pm_b pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_UNEXPECTED_BLOCK); } -/******************************************************************************/ -/* Scope node functions */ -/******************************************************************************/ - -// Generate a scope node from the given node. -void -pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser) { - scope->base.type = PM_SCOPE_NODE; - scope->base.location.start = node->location.start; - scope->base.location.end = node->location.end; - - scope->previous = previous; - scope->parser = parser; - scope->ast_node = (pm_node_t *)node; - scope->parameters = NULL; - scope->body = NULL; - scope->constants = NULL; - if (previous) { - scope->constants = previous->constants; - } - scope->index_lookup_table = NULL; - - pm_constant_id_list_init(&scope->locals); - - switch (PM_NODE_TYPE(node)) { - case PM_BLOCK_NODE: { - pm_block_node_t *cast = (pm_block_node_t *) node; - if (cast->parameters) scope->parameters = cast->parameters->parameters; - scope->body = cast->body; - scope->locals = cast->locals; - break; - } - case PM_CLASS_NODE: { - pm_class_node_t *cast = (pm_class_node_t *) node; - scope->body = cast->body; - scope->locals = cast->locals; - break; - } - case PM_DEF_NODE: { - pm_def_node_t *cast = (pm_def_node_t *) node; - scope->parameters = cast->parameters; - scope->body = cast->body; - scope->locals = cast->locals; - break; - } - case PM_FOR_NODE: { - pm_for_node_t *cast = (pm_for_node_t *)node; - scope->body = (pm_node_t *)cast->statements; - break; - } - case PM_LAMBDA_NODE: { - pm_lambda_node_t *cast = (pm_lambda_node_t *) node; - if (cast->parameters) scope->parameters = cast->parameters->parameters; - scope->body = cast->body; - scope->locals = cast->locals; - break; - } - case PM_MODULE_NODE: { - pm_module_node_t *cast = (pm_module_node_t *) node; - scope->body = cast->body; - scope->locals = cast->locals; - break; - } - case PM_PROGRAM_NODE: { - pm_program_node_t *cast = (pm_program_node_t *) node; - scope->body = (pm_node_t *) cast->statements; - scope->locals = cast->locals; - break; - } - case PM_SINGLETON_CLASS_NODE: { - pm_singleton_class_node_t *cast = (pm_singleton_class_node_t *) node; - scope->body = cast->body; - scope->locals = cast->locals; - break; - } - default: - assert(false && "unreachable"); - break; - } -} - /******************************************************************************/ /* Node creation functions */ /******************************************************************************/ @@ -775,11 +683,15 @@ parse_decimal_number(pm_parser_t *parser, const uint8_t *start, const uint8_t *e return (uint32_t) value; } +// When you have an encoding flag on a regular expression, it takes precedence +// over all of the previously set encoding flags. So we need to mask off any +// previously set encoding flags before setting the new one. +#define PM_REGULAR_EXPRESSION_ENCODING_MASK ~(PM_REGULAR_EXPRESSION_FLAGS_EUC_JP | PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT | PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J | PM_REGULAR_EXPRESSION_FLAGS_UTF_8) + // Parse out the options for a regular expression. static inline pm_node_flags_t pm_regular_expression_flags_create(const pm_token_t *closing) { pm_node_flags_t flags = 0; - pm_node_flags_t mask = (uint16_t) 0xFF0F; if (closing->type == PM_TOKEN_REGEXP_END) { for (const uint8_t *flag = closing->start + 1; flag < closing->end; flag++) { @@ -789,10 +701,10 @@ pm_regular_expression_flags_create(const pm_token_t *closing) { case 'x': flags |= PM_REGULAR_EXPRESSION_FLAGS_EXTENDED; break; case 'o': flags |= PM_REGULAR_EXPRESSION_FLAGS_ONCE; break; - case 'e': flags &= mask; flags |= PM_REGULAR_EXPRESSION_FLAGS_EUC_JP; break; - case 'n': flags &= mask; flags |= PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT; break; - case 's': flags &= mask; flags |= PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J; break; - case 'u': flags &= mask; flags |= PM_REGULAR_EXPRESSION_FLAGS_UTF_8; break; + case 'e': flags = (pm_node_flags_t) (((pm_node_flags_t) (flags & PM_REGULAR_EXPRESSION_ENCODING_MASK)) | PM_REGULAR_EXPRESSION_FLAGS_EUC_JP); break; + case 'n': flags = (pm_node_flags_t) (((pm_node_flags_t) (flags & PM_REGULAR_EXPRESSION_ENCODING_MASK)) | PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT); break; + case 's': flags = (pm_node_flags_t) (((pm_node_flags_t) (flags & PM_REGULAR_EXPRESSION_ENCODING_MASK)) | PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J); break; + case 'u': flags = (pm_node_flags_t) (((pm_node_flags_t) (flags & PM_REGULAR_EXPRESSION_ENCODING_MASK)) | PM_REGULAR_EXPRESSION_FLAGS_UTF_8); break; default: assert(false && "unreachable"); } @@ -802,6 +714,8 @@ pm_regular_expression_flags_create(const pm_token_t *closing) { return flags; } +#undef PM_REGULAR_EXPRESSION_ENCODING_MASK + // Allocate and initialize a new StatementsNode node. static pm_statements_node_t * pm_statements_node_create(pm_parser_t *parser); @@ -1458,7 +1372,7 @@ pm_call_node_aref_create(pm_parser_t *parser, pm_node_t *receiver, pm_arguments_ node->closing_loc = arguments->closing_loc; node->block = arguments->block; - node->name = pm_parser_constant_id_static(parser, "[]", 2); + node->name = pm_parser_constant_id_constant(parser, "[]", 2); return node; } @@ -1558,7 +1472,7 @@ pm_call_node_not_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *me node->arguments = arguments->arguments; node->closing_loc = arguments->closing_loc; - node->name = pm_parser_constant_id_static(parser, "!", 1); + node->name = pm_parser_constant_id_constant(parser, "!", 1); return node; } @@ -1585,7 +1499,7 @@ pm_call_node_shorthand_create(pm_parser_t *parser, pm_node_t *receiver, pm_token node->base.flags |= PM_CALL_NODE_FLAGS_SAFE_NAVIGATION; } - node->name = pm_parser_constant_id_static(parser, "call", 4); + node->name = pm_parser_constant_id_constant(parser, "call", 4); return node; } @@ -1600,7 +1514,7 @@ pm_call_node_unary_create(pm_parser_t *parser, pm_token_t *operator, pm_node_t * node->receiver = receiver; node->message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator); - node->name = pm_parser_constant_id_static(parser, name, strlen(name)); + node->name = pm_parser_constant_id_constant(parser, name, strlen(name)); return node; } @@ -1624,11 +1538,38 @@ pm_call_node_variable_call_p(pm_call_node_t *node) { return node->base.flags & PM_CALL_NODE_FLAGS_VARIABLE_CALL; } +// Returns whether or not this call is to the [] method in the index form (as +// opposed to `foo.[]`). +static inline bool +pm_call_node_index_p(pm_call_node_t *node) { + return ( + (node->call_operator_loc.start == NULL) && + (node->message_loc.start != NULL) && + (node->message_loc.start[0] == '[') && + (node->message_loc.end[-1] == ']') + ); +} + +// Returns whether or not this call can be used on the left-hand side of an +// operator assignment. +static inline bool +pm_call_node_writable_p(pm_call_node_t *node) { + return ( + (node->message_loc.start != NULL) && + (node->message_loc.end[-1] != '!') && + (node->message_loc.end[-1] != '?') && + (node->opening_loc.start == NULL) && + (node->arguments == NULL) && + (node->block == NULL) + ); +} + // Initialize the read name by reading the write name and chopping off the '='. static void pm_call_write_read_name_init(pm_parser_t *parser, pm_constant_id_t *read_name, pm_constant_id_t *write_name) { pm_constant_t *write_constant = pm_constant_pool_id_to_constant(&parser->constant_pool, *write_name); - if (write_constant->length >= 1) { + + if (write_constant->length > 0) { size_t length = write_constant->length - 1; void *memory = malloc(length); @@ -1637,7 +1578,7 @@ pm_call_write_read_name_init(pm_parser_t *parser, pm_constant_id_t *read_name, p *read_name = pm_constant_pool_insert_owned(&parser->constant_pool, (uint8_t *) memory, length); } else { // We can get here if the message was missing because of a syntax error. - *read_name = pm_parser_constant_id_static(parser, "", 0); + *read_name = pm_parser_constant_id_constant(parser, "", 0); } } @@ -1660,9 +1601,6 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const .receiver = target->receiver, .call_operator_loc = target->call_operator_loc, .message_loc = target->message_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, .read_name = 0, .write_name = target->name, .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), @@ -1679,6 +1617,39 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const return node; } +// Allocate and initialize a new IndexAndWriteNode node. +static pm_index_and_write_node_t * +pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { + assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); + pm_index_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_and_write_node_t); + + *node = (pm_index_and_write_node_t) { + { + .type = PM_INDEX_AND_WRITE_NODE, + .flags = target->base.flags, + .location = { + .start = target->base.location.start, + .end = value->location.end + } + }, + .receiver = target->receiver, + .call_operator_loc = target->call_operator_loc, + .opening_loc = target->opening_loc, + .arguments = target->arguments, + .closing_loc = target->closing_loc, + .block = target->block, + .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .value = value + }; + + // Here we're going to free the target, since it is no longer necessary. + // However, we don't want to call `pm_node_destroy` because we want to keep + // around all of its children since we just reused them. + free(target); + + return node; +} + // Allocate a new CallOperatorWriteNode node. static pm_call_operator_write_node_t * pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { @@ -1697,9 +1668,6 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, .receiver = target->receiver, .call_operator_loc = target->call_operator_loc, .message_loc = target->message_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, .read_name = 0, .write_name = target->name, .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), @@ -1717,7 +1685,40 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, return node; } -// Allocate and initialize a new CallOperatorOrWriteNode node. +// Allocate a new IndexOperatorWriteNode node. +static pm_index_operator_write_node_t * +pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { + pm_index_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_operator_write_node_t); + + *node = (pm_index_operator_write_node_t) { + { + .type = PM_INDEX_OPERATOR_WRITE_NODE, + .flags = target->base.flags, + .location = { + .start = target->base.location.start, + .end = value->location.end + } + }, + .receiver = target->receiver, + .call_operator_loc = target->call_operator_loc, + .opening_loc = target->opening_loc, + .arguments = target->arguments, + .closing_loc = target->closing_loc, + .block = target->block, + .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .value = value + }; + + // Here we're going to free the target, since it is no longer necessary. + // However, we don't want to call `pm_node_destroy` because we want to keep + // around all of its children since we just reused them. + free(target); + + return node; +} + +// Allocate and initialize a new CallOrWriteNode node. static pm_call_or_write_node_t * pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); @@ -1736,9 +1737,6 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const .receiver = target->receiver, .call_operator_loc = target->call_operator_loc, .message_loc = target->message_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, .read_name = 0, .write_name = target->name, .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), @@ -1755,6 +1753,39 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const return node; } +// Allocate and initialize a new IndexOrWriteNode node. +static pm_index_or_write_node_t * +pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { + assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); + pm_index_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_or_write_node_t); + + *node = (pm_index_or_write_node_t) { + { + .type = PM_INDEX_OR_WRITE_NODE, + .flags = target->base.flags, + .location = { + .start = target->base.location.start, + .end = value->location.end + } + }, + .receiver = target->receiver, + .call_operator_loc = target->call_operator_loc, + .opening_loc = target->opening_loc, + .arguments = target->arguments, + .closing_loc = target->closing_loc, + .block = target->block, + .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .value = value + }; + + // Here we're going to free the target, since it is no longer necessary. + // However, we don't want to call `pm_node_destroy` because we want to keep + // around all of its children since we just reused them. + free(target); + + return node; +} + // Allocate and initialize a new CapturePatternNode node. static pm_capture_pattern_node_t * pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *target, const pm_token_t *operator) { @@ -2557,10 +2588,10 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening }, }, .constant = NULL, - .kwrest = NULL, .opening_loc = PM_LOCATION_TOKEN_VALUE(opening), .closing_loc = PM_LOCATION_TOKEN_VALUE(closing), - .assocs = PM_EMPTY_NODE_LIST + .elements = PM_EMPTY_NODE_LIST, + .rest = NULL }; return node; @@ -2568,27 +2599,44 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening // Allocate and initialize a new hash pattern node. static pm_hash_pattern_node_t * -pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *assocs) { +pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *elements, pm_node_t *rest) { pm_hash_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_hash_pattern_node_t); + const uint8_t *start; + const uint8_t *end; + + if (elements->size > 0) { + if (rest) { + start = elements->nodes[0]->location.start; + end = rest->location.end; + } else { + start = elements->nodes[0]->location.start; + end = elements->nodes[elements->size - 1]->location.end; + } + } else { + assert(rest != NULL); + start = rest->location.start; + end = rest->location.end; + } + *node = (pm_hash_pattern_node_t) { { .type = PM_HASH_PATTERN_NODE, .location = { - .start = assocs->nodes[0]->location.start, - .end = assocs->nodes[assocs->size - 1]->location.end + .start = start, + .end = end }, }, .constant = NULL, - .kwrest = NULL, - .assocs = PM_EMPTY_NODE_LIST, + .elements = PM_EMPTY_NODE_LIST, + .rest = rest, .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }; - for (size_t index = 0; index < assocs->size; index++) { - pm_node_t *assoc = assocs->nodes[index]; - pm_node_list_append(&node->assocs, assoc); + for (size_t index = 0; index < elements->size; index++) { + pm_node_t *element = elements->nodes[index]; + pm_node_list_append(&node->elements, element); } return node; @@ -3585,7 +3633,9 @@ pm_multi_target_node_create(pm_parser_t *parser) { .type = PM_MULTI_TARGET_NODE, .location = { .start = NULL, .end = NULL } }, - .targets = PM_EMPTY_NODE_LIST, + .lefts = PM_EMPTY_NODE_LIST, + .rest = NULL, + .rights = PM_EMPTY_NODE_LIST, .lparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .rparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE }; @@ -3595,8 +3645,19 @@ pm_multi_target_node_create(pm_parser_t *parser) { // Append a target to a MultiTargetNode node. static void -pm_multi_target_node_targets_append(pm_multi_target_node_t *node, pm_node_t *target) { - pm_node_list_append(&node->targets, target); +pm_multi_target_node_targets_append(pm_parser_t *parser, pm_multi_target_node_t *node, pm_node_t *target) { + if (PM_NODE_TYPE_P(target, PM_SPLAT_NODE)) { + if (node->rest == NULL) { + node->rest = target; + } else { + pm_parser_err_node(parser, target, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS); + pm_node_list_append(&node->rights, target); + } + } else if (node->rest == NULL) { + pm_node_list_append(&node->lefts, target); + } else { + pm_node_list_append(&node->rights, target); + } if (node->base.location.start == NULL || (node->base.location.start > target->location.start)) { node->base.location.start = target->location.start; @@ -3607,6 +3668,20 @@ pm_multi_target_node_targets_append(pm_multi_target_node_t *node, pm_node_t *tar } } +// Set the opening of a MultiTargetNode node. +static void +pm_multi_target_node_opening_set(pm_multi_target_node_t *node, const pm_token_t *lparen) { + node->base.location.start = lparen->start; + node->lparen_loc = PM_LOCATION_TOKEN_VALUE(lparen); +} + +// Set the closing of a MultiTargetNode node. +static void +pm_multi_target_node_closing_set(pm_multi_target_node_t *node, const pm_token_t *rparen) { + node->base.location.end = rparen->end; + node->rparen_loc = PM_LOCATION_TOKEN_VALUE(rparen); +} + // Allocate a new MultiWriteNode node. static pm_multi_write_node_t * pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, const pm_token_t *operator, pm_node_t *value) { @@ -3620,7 +3695,9 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, .end = value->location.end } }, - .targets = target->targets, + .lefts = target->lefts, + .rest = target->rest, + .rights = target->rights, .lparen_loc = target->lparen_loc, .rparen_loc = target->rparen_loc, .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), @@ -4047,37 +4124,6 @@ pm_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening return pm_regular_expression_node_create_unescaped(parser, opening, content, closing, &PM_EMPTY_STRING); } -// Allocate a new RequiredDestructuredParameterNode node. -static pm_required_destructured_parameter_node_t * -pm_required_destructured_parameter_node_create(pm_parser_t *parser, const pm_token_t *opening) { - pm_required_destructured_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_required_destructured_parameter_node_t); - - *node = (pm_required_destructured_parameter_node_t) { - { - .type = PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE, - .location = PM_LOCATION_TOKEN_VALUE(opening) - }, - .opening_loc = PM_LOCATION_TOKEN_VALUE(opening), - .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, - .parameters = PM_EMPTY_NODE_LIST - }; - - return node; -} - -// Append a new parameter to the given RequiredDestructuredParameterNode node. -static void -pm_required_destructured_parameter_node_append_parameter(pm_required_destructured_parameter_node_t *node, pm_node_t *parameter) { - pm_node_list_append(&node->parameters, parameter); -} - -// Set the closing token of the given RequiredDestructuredParameterNode node. -static void -pm_required_destructured_parameter_node_closing_set(pm_required_destructured_parameter_node_t *node, const pm_token_t *closing) { - node->closing_loc = PM_LOCATION_TOKEN_VALUE(closing); - node->base.location.end = closing->end; -} - // Allocate a new RequiredParameterNode node. static pm_required_parameter_node_t * pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) { @@ -4994,6 +5040,13 @@ pm_parser_local_add(pm_parser_t *parser, pm_constant_id_t constant_id) { } } +// Add a local variable from a constant string to the current scope. +static inline void +pm_parser_local_add_constant(pm_parser_t *parser, const char *start, size_t length) { + pm_constant_id_t constant_id = pm_parser_constant_id_constant(parser, start, length); + if (constant_id != 0) pm_parser_local_add(parser, constant_id); +} + // Add a local variable from a location to the current scope. static pm_constant_id_t pm_parser_local_add_location(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { @@ -5009,10 +5062,11 @@ pm_parser_local_add_token(pm_parser_t *parser, pm_token_t *token) { } // Add a local variable from an owned string to the current scope. -static inline void +static pm_constant_id_t pm_parser_local_add_owned(pm_parser_t *parser, const uint8_t *start, size_t length) { pm_constant_id_t constant_id = pm_parser_constant_id_owned(parser, start, length); if (constant_id != 0) pm_parser_local_add(parser, constant_id); + return constant_id; } // Add a parameter name to the current scope and check whether the name of the @@ -5553,6 +5607,8 @@ context_terminator(pm_context_t context, pm_token_t *token) { case PM_CONTEXT_FOR: case PM_CONTEXT_ENSURE: return token->type == PM_TOKEN_KEYWORD_END; + case PM_CONTEXT_FOR_INDEX: + return token->type == PM_TOKEN_KEYWORD_IN; case PM_CONTEXT_CASE_WHEN: return token->type == PM_TOKEN_KEYWORD_WHEN || token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_ELSE; case PM_CONTEXT_CASE_IN: @@ -6308,24 +6364,24 @@ escape_byte(uint8_t value, const uint8_t flags) { static inline void escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t *start, const uint8_t *end, uint32_t value) { if (value <= 0x7F) { // 0xxxxxxx - pm_buffer_append_u8(buffer, (uint8_t) value); + pm_buffer_append_byte(buffer, (uint8_t) value); } else if (value <= 0x7FF) { // 110xxxxx 10xxxxxx - pm_buffer_append_u8(buffer, (uint8_t) (0xC0 | (value >> 6))); - pm_buffer_append_u8(buffer, (uint8_t) (0x80 | (value & 0x3F))); + pm_buffer_append_byte(buffer, (uint8_t) (0xC0 | (value >> 6))); + pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F))); } else if (value <= 0xFFFF) { // 1110xxxx 10xxxxxx 10xxxxxx - pm_buffer_append_u8(buffer, (uint8_t) (0xE0 | (value >> 12))); - pm_buffer_append_u8(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F))); - pm_buffer_append_u8(buffer, (uint8_t) (0x80 | (value & 0x3F))); + pm_buffer_append_byte(buffer, (uint8_t) (0xE0 | (value >> 12))); + pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F))); + pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F))); } else if (value <= 0x10FFFF) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - pm_buffer_append_u8(buffer, (uint8_t) (0xF0 | (value >> 18))); - pm_buffer_append_u8(buffer, (uint8_t) (0x80 | ((value >> 12) & 0x3F))); - pm_buffer_append_u8(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F))); - pm_buffer_append_u8(buffer, (uint8_t) (0x80 | (value & 0x3F))); + pm_buffer_append_byte(buffer, (uint8_t) (0xF0 | (value >> 18))); + pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 12) & 0x3F))); + pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F))); + pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F))); } else { pm_parser_err(parser, start, end, PM_ERR_ESCAPE_INVALID_UNICODE); - pm_buffer_append_u8(buffer, 0xEF); - pm_buffer_append_u8(buffer, 0xBF); - pm_buffer_append_u8(buffer, 0xBD); + pm_buffer_append_byte(buffer, 0xEF); + pm_buffer_append_byte(buffer, 0xBF); + pm_buffer_append_byte(buffer, 0xBD); } } @@ -6351,18 +6407,18 @@ escape_write_byte(pm_buffer_t *buffer, uint8_t flags, uint8_t byte) { uint8_t byte2 = (uint8_t) (byte & 0xF); if (byte1 >= 0xA) { - pm_buffer_append_u8(buffer, (uint8_t) ((byte1 - 0xA) + 'A')); + pm_buffer_append_byte(buffer, (uint8_t) ((byte1 - 0xA) + 'A')); } else { - pm_buffer_append_u8(buffer, (uint8_t) (byte1 + '0')); + pm_buffer_append_byte(buffer, (uint8_t) (byte1 + '0')); } if (byte2 >= 0xA) { - pm_buffer_append_u8(buffer, (uint8_t) (byte2 - 0xA + 'A')); + pm_buffer_append_byte(buffer, (uint8_t) (byte2 - 0xA + 'A')); } else { - pm_buffer_append_u8(buffer, (uint8_t) (byte2 + '0')); + pm_buffer_append_byte(buffer, (uint8_t) (byte2 + '0')); } } else { - pm_buffer_append_u8(buffer, byte); + pm_buffer_append_byte(buffer, byte); } } @@ -6372,57 +6428,57 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) { switch (peek(parser)) { case '\\': { parser->current.end++; - pm_buffer_append_u8(buffer, '\\'); + pm_buffer_append_byte(buffer, '\\'); return; } case '\'': { parser->current.end++; - pm_buffer_append_u8(buffer, '\''); + pm_buffer_append_byte(buffer, '\''); return; } case 'a': { parser->current.end++; - pm_buffer_append_u8(buffer, '\a'); + pm_buffer_append_byte(buffer, '\a'); return; } case 'b': { parser->current.end++; - pm_buffer_append_u8(buffer, '\b'); + pm_buffer_append_byte(buffer, '\b'); return; } case 'e': { parser->current.end++; - pm_buffer_append_u8(buffer, '\033'); + pm_buffer_append_byte(buffer, '\033'); return; } case 'f': { parser->current.end++; - pm_buffer_append_u8(buffer, '\f'); + pm_buffer_append_byte(buffer, '\f'); return; } case 'n': { parser->current.end++; - pm_buffer_append_u8(buffer, '\n'); + pm_buffer_append_byte(buffer, '\n'); return; } case 'r': { parser->current.end++; - pm_buffer_append_u8(buffer, '\r'); + pm_buffer_append_byte(buffer, '\r'); return; } case 's': { parser->current.end++; - pm_buffer_append_u8(buffer, ' '); + pm_buffer_append_byte(buffer, ' '); return; } case 't': { parser->current.end++; - pm_buffer_append_u8(buffer, '\t'); + pm_buffer_append_byte(buffer, '\t'); return; } case 'v': { parser->current.end++; - pm_buffer_append_u8(buffer, '\v'); + pm_buffer_append_byte(buffer, '\v'); return; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { @@ -6439,7 +6495,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) { } } - pm_buffer_append_u8(buffer, value); + pm_buffer_append_byte(buffer, value); return; } case 'x': { @@ -6461,7 +6517,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) { if (flags & PM_ESCAPE_FLAG_REGEXP) { pm_buffer_append_bytes(buffer, start, (size_t) (parser->current.end - start)); } else { - pm_buffer_append_u8(buffer, value); + pm_buffer_append_byte(buffer, value); } } else { pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_HEXADECIMAL); @@ -6655,14 +6711,14 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) { case '\r': { if (peek_offset(parser, 1) == '\n') { parser->current.end += 2; - pm_buffer_append_u8(buffer, '\n'); + pm_buffer_append_byte(buffer, '\n'); return; } } /* fallthrough */ default: { if (parser->current.end < parser->end) { - pm_buffer_append_u8(buffer, *parser->current.end++); + pm_buffer_append_byte(buffer, *parser->current.end++); } return; } @@ -6913,19 +6969,10 @@ typedef struct { const uint8_t *cursor; } pm_token_buffer_t; -static inline bool -pm_token_buffer_init(pm_token_buffer_t *token_buffer) { - if (!pm_buffer_init(&token_buffer->buffer)) { - return false; - } - token_buffer->cursor = NULL; - return true; -} - // Push the given byte into the token buffer. static inline void pm_token_buffer_push(pm_token_buffer_t *token_buffer, uint8_t byte) { - pm_buffer_append_u8(&token_buffer->buffer, byte); + pm_buffer_append_byte(&token_buffer->buffer, byte); } // When we're about to return from lexing the current token and we know for sure @@ -8222,8 +8269,7 @@ parser_lex(pm_parser_t *parser) { // If we haven't found an escape yet, then this buffer will be // unallocated since we can refer directly to the source string. - pm_token_buffer_t token_buffer; - pm_token_buffer_init(&token_buffer); + pm_token_buffer_t token_buffer = { { 0 }, 0 }; while (breakpoint != NULL) { // If we hit a null byte, skip directly past it. @@ -8399,8 +8445,7 @@ parser_lex(pm_parser_t *parser) { // characters. const uint8_t *breakpoints = lex_mode->as.regexp.breakpoints; const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); - pm_token_buffer_t token_buffer; - pm_token_buffer_init(&token_buffer); + pm_token_buffer_t token_buffer = { { 0 }, 0 }; while (breakpoint != NULL) { // If we hit a null byte, skip directly past it. @@ -8589,8 +8634,7 @@ parser_lex(pm_parser_t *parser) { // If we haven't found an escape yet, then this buffer will be // unallocated since we can refer directly to the source string. - pm_token_buffer_t token_buffer; - pm_token_buffer_init(&token_buffer); + pm_token_buffer_t token_buffer = { { 0 }, 0 }; while (breakpoint != NULL) { // If we hit the incrementor, then we'll increment then nesting and @@ -8851,8 +8895,7 @@ parser_lex(pm_parser_t *parser) { } const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); - pm_token_buffer_t token_buffer; - pm_token_buffer_init(&token_buffer); + pm_token_buffer_t token_buffer = { { 0 }, 0 }; bool was_escaped_newline = false; while (breakpoint != NULL) { @@ -9470,10 +9513,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) { splat->expression = parse_target(parser, splat->expression); } - pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser); - pm_multi_target_node_targets_append(multi_target, (pm_node_t *) splat); - - return (pm_node_t *) multi_target; + return (pm_node_t *) splat; } case PM_CALL_NODE: { pm_call_node_t *call = (pm_call_node_t *) target; @@ -9535,7 +9575,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) { (call->block == NULL) ) { // Replace the name with "[]=". - call->name = pm_parser_constant_id_static(parser, "[]=", 3); + call->name = pm_parser_constant_id_constant(parser, "[]=", 3); return target; } } @@ -9549,7 +9589,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) { } } -// Parse a write targets and validate that it is in a valid position for +// Parse a write target and validate that it is in a valid position for // assignment. static pm_node_t * parse_target_validate(pm_parser_t *parser, pm_node_t *target) { @@ -9620,7 +9660,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod } pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser); - pm_multi_target_node_targets_append(multi_target, (pm_node_t *) splat); + pm_multi_target_node_targets_append(parser, multi_target, (pm_node_t *) splat); return (pm_node_t *) pm_multi_write_node_create(parser, multi_target, operator, value); } @@ -9702,7 +9742,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod target->location.end = value->location.end; // Replace the name with "[]=". - call->name = pm_parser_constant_id_static(parser, "[]=", 3); + call->name = pm_parser_constant_id_constant(parser, "[]=", 3); return target; } @@ -9736,7 +9776,7 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b bool has_splat = PM_NODE_TYPE_P(first_target, PM_SPLAT_NODE); pm_multi_target_node_t *result = pm_multi_target_node_create(parser); - pm_multi_target_node_targets_append(result, parse_target(parser, first_target)); + pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target)); while (accept1(parser, PM_TOKEN_COMMA)) { if (accept1(parser, PM_TOKEN_USTAR)) { @@ -9756,19 +9796,19 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b } pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name); - pm_multi_target_node_targets_append(result, splat); + pm_multi_target_node_targets_append(parser, result, splat); has_splat = true; } else if (token_begins_expression_p(parser->current.type)) { pm_node_t *target = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA); target = parse_target(parser, target); - pm_multi_target_node_targets_append(result, target); - } else { + pm_multi_target_node_targets_append(parser, result, target); + } else if (!match1(parser, PM_TOKEN_EOF)) { // If we get here, then we have a trailing , in a multi target node. // We need to indicate this somehow in the tree, so we'll add an // anonymous splat. pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &parser->previous, NULL); - pm_multi_target_node_targets_append(result, splat); + pm_multi_target_node_targets_append(parser, result, splat); break; } } @@ -9861,9 +9901,11 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { } // Parse all of the elements of a hash. -static void +// Returns true if a double splat was found +static bool parse_assocs(pm_parser_t *parser, pm_node_t *node) { assert(PM_NODE_TYPE_P(node, PM_HASH_NODE) || PM_NODE_TYPE_P(node, PM_KEYWORD_HASH_NODE)); + bool contains_keyword_splat = false; while (true) { pm_node_t *element; @@ -9881,6 +9923,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) { } element = (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator); + contains_keyword_splat = true; break; } case PM_TOKEN_LABEL: { @@ -9939,7 +9982,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) { } // If there's no comma after the element, then we're done. - if (!accept1(parser, PM_TOKEN_COMMA)) return; + if (!accept1(parser, PM_TOKEN_COMMA)) break; // If the next element starts with a label or a **, then we know we have // another element in the hash, so we'll continue parsing. @@ -9950,8 +9993,9 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) { if (token_begins_expression_p(parser->current.type)) continue; // Otherwise by default we will exit out of this loop. - return; + break; } + return contains_keyword_splat; } // Append an argument to a list of arguments. @@ -9999,12 +10043,16 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser); argument = (pm_node_t *) hash; + bool contains_keyword_splat = false; if (!match7(parser, terminator, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) { - parse_assocs(parser, (pm_node_t *) hash); + contains_keyword_splat = parse_assocs(parser, (pm_node_t *) hash); } parsed_bare_hash = true; parse_arguments_append(parser, arguments, argument); + if (contains_keyword_splat) { + arguments->arguments->base.flags |= PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT; + } break; } case PM_TOKEN_UAMPERSAND: { @@ -10078,6 +10126,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for argument = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_ARGUMENT); } + bool contains_keyword_splat = false; if (pm_symbol_node_label_p(argument) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) { if (parsed_bare_hash) { pm_parser_err_previous(parser, PM_ERR_ARGUMENT_BARE_HASH); @@ -10104,13 +10153,16 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for token_begins_expression_p(parser->current.type) || match2(parser, PM_TOKEN_USTAR_STAR, PM_TOKEN_LABEL) )) { - parse_assocs(parser, (pm_node_t *) bare_hash); + contains_keyword_splat = parse_assocs(parser, (pm_node_t *) bare_hash); } parsed_bare_hash = true; } parse_arguments_append(parser, arguments, argument); + if (contains_keyword_splat) { + arguments->arguments->base.flags |= PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT; + } break; } } @@ -10146,34 +10198,27 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for // end // // It can recurse infinitely down, and splats are allowed to group arguments. -static pm_required_destructured_parameter_node_t * +static pm_multi_target_node_t * parse_required_destructured_parameter(pm_parser_t *parser) { expect1(parser, PM_TOKEN_PARENTHESIS_LEFT, PM_ERR_EXPECT_LPAREN_REQ_PARAMETER); - pm_token_t opening = parser->previous; - pm_required_destructured_parameter_node_t *node = pm_required_destructured_parameter_node_create(parser, &opening); - bool parsed_splat = false; + pm_multi_target_node_t *node = pm_multi_target_node_create(parser); + pm_multi_target_node_opening_set(node, &parser->previous); do { pm_node_t *param; - if (node->parameters.size > 0 && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { - if (parsed_splat) { - pm_parser_err_previous(parser, PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT); - } - + // If we get here then we have a trailing comma. In this case we'll + // create an implicit splat node. + if (node->lefts.size > 0 && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { param = (pm_node_t *) pm_splat_node_create(parser, &parser->previous, NULL); - pm_required_destructured_parameter_node_append_parameter(node, param); + pm_multi_target_node_targets_append(parser, node, param); break; } if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { param = (pm_node_t *) parse_required_destructured_parameter(parser); } else if (accept1(parser, PM_TOKEN_USTAR)) { - if (parsed_splat) { - pm_parser_err_previous(parser, PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT); - } - pm_token_t star = parser->previous; pm_node_t *value = NULL; @@ -10185,7 +10230,6 @@ parse_required_destructured_parameter(pm_parser_t *parser) { } param = (pm_node_t *) pm_splat_node_create(parser, &star, value); - parsed_splat = true; } else { expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_EXPECT_IDENT_REQ_PARAMETER); pm_token_t name = parser->previous; @@ -10195,11 +10239,11 @@ parse_required_destructured_parameter(pm_parser_t *parser) { pm_parser_local_add_token(parser, &name); } - pm_required_destructured_parameter_node_append_parameter(node, param); + pm_multi_target_node_targets_append(parser, node, param); } while (accept1(parser, PM_TOKEN_COMMA)); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN_REQ_PARAMETER); - pm_required_destructured_parameter_node_closing_set(node, &parser->previous); + pm_multi_target_node_closing_set(node, &parser->previous); return node; } @@ -10323,11 +10367,17 @@ parse_parameters( if (!allows_forwarding_parameter) { pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); } + if (order > PM_PARAMETERS_ORDER_NOTHING_AFTER) { update_parameter_state(parser, &parser->current, &order); parser_lex(parser); - pm_parser_local_add_token(parser, &parser->previous); + if (allows_forwarding_parameter) { + pm_parser_local_add_constant(parser, "*", 1); + pm_parser_local_add_constant(parser, "&", 1); + pm_parser_local_add_token(parser, &parser->previous); + } + pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous); if (params->keyword_rest != NULL) { // If we already have a keyword rest parameter, then we replace it with the @@ -10342,6 +10392,7 @@ parse_parameters( update_parameter_state(parser, &parser->current, &order); parser_lex(parser); } + break; } case PM_TOKEN_CLASS_VARIABLE: @@ -11678,28 +11729,40 @@ parse_pattern_keyword_rest(pm_parser_t *parser) { // Parse a hash pattern. static pm_hash_pattern_node_t * parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) { - if (PM_NODE_TYPE_P(first_assoc, PM_ASSOC_NODE)) { - if (!match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - // Here we have a value for the first assoc in the list, so we will parse it - // now and update the first assoc. - pm_node_t *value = parse_pattern(parser, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); - - pm_assoc_node_t *assoc = (pm_assoc_node_t *) first_assoc; - assoc->base.location.end = value->location.end; - assoc->value = value; - } else { - pm_node_t *key = ((pm_assoc_node_t *) first_assoc)->key; + pm_node_list_t assocs = PM_EMPTY_NODE_LIST; + pm_node_t *rest = NULL; - if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) { - const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; - pm_parser_local_add_location(parser, value_loc->start, value_loc->end); + switch (PM_NODE_TYPE(first_assoc)) { + case PM_ASSOC_NODE: { + if (!match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { + // Here we have a value for the first assoc in the list, so we will + // parse it now and update the first assoc. + pm_node_t *value = parse_pattern(parser, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + + pm_assoc_node_t *assoc = (pm_assoc_node_t *) first_assoc; + assoc->base.location.end = value->location.end; + assoc->value = value; + } else { + pm_node_t *key = ((pm_assoc_node_t *) first_assoc)->key; + + if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) { + const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; + pm_parser_local_add_location(parser, value_loc->start, value_loc->end); + } } + + pm_node_list_append(&assocs, first_assoc); + break; } + case PM_ASSOC_SPLAT_NODE: + case PM_NO_KEYWORDS_PARAMETER_NODE: + rest = first_assoc; + break; + default: + assert(false); + break; } - pm_node_list_t assocs = PM_EMPTY_NODE_LIST; - pm_node_list_append(&assocs, first_assoc); - // If there are any other assocs, then we'll parse them now. while (accept1(parser, PM_TOKEN_COMMA)) { // Here we need to break to support trailing commas. @@ -11730,7 +11793,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) { pm_node_list_append(&assocs, assoc); } - pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs); + pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs, rest); free(assocs.nodes); return node; @@ -11815,32 +11878,45 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { // pattern node. node = pm_hash_pattern_node_empty_create(parser, &opening, &parser->previous); } else { - pm_node_t *key; + pm_node_t *first_assoc; switch (parser->current.type) { - case PM_TOKEN_LABEL: + case PM_TOKEN_LABEL: { parser_lex(parser); - key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); + + pm_symbol_node_t *key = pm_symbol_node_label_create(parser, &parser->previous); + pm_token_t operator = not_provided(parser); + + first_assoc = (pm_node_t *) pm_assoc_node_create(parser, (pm_node_t *) key, &operator, NULL); break; + } case PM_TOKEN_USTAR_STAR: - key = parse_pattern_keyword_rest(parser); + first_assoc = parse_pattern_keyword_rest(parser); break; - case PM_TOKEN_STRING_BEGIN: - key = parse_expression(parser, PM_BINDING_POWER_MAX, PM_ERR_PATTERN_HASH_KEY); + case PM_TOKEN_STRING_BEGIN: { + pm_node_t *key = parse_expression(parser, PM_BINDING_POWER_MAX, PM_ERR_PATTERN_HASH_KEY); + pm_token_t operator = not_provided(parser); + if (!pm_symbol_node_label_p(key)) { pm_parser_err_node(parser, key, PM_ERR_PATTERN_HASH_KEY_LABEL); } + first_assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, NULL); break; - default: + } + default: { parser_lex(parser); pm_parser_err_previous(parser, PM_ERR_PATTERN_HASH_KEY); - key = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end); + + pm_missing_node_t *key = pm_missing_node_create(parser, parser->previous.start, parser->previous.end); + pm_token_t operator = not_provided(parser); + + first_assoc = (pm_node_t *) pm_assoc_node_create(parser, (pm_node_t *) key, &operator, NULL); break; + } } - pm_token_t operator = not_provided(parser); - node = parse_pattern_hash(parser, (pm_node_t *) pm_assoc_node_create(parser, key, &operator, NULL)); + node = parse_pattern_hash(parser, first_assoc); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE); @@ -12468,16 +12544,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { parser_lex(parser); pm_accepts_block_stack_pop(parser); - // If we have a single statement and are ending on a right - // parenthesis, then we need to check if this is possibly a - // multiple target node. - if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE)) { + if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE) || PM_NODE_TYPE_P(statement, PM_SPLAT_NODE)) { + // If we have a single statement and are ending on a right + // parenthesis, then we need to check if this is possibly a + // multiple target node. pm_multi_target_node_t *multi_target; - if (((pm_multi_target_node_t *) statement)->lparen_loc.start == NULL) { + + if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE) && ((pm_multi_target_node_t *) statement)->lparen_loc.start == NULL) { multi_target = (pm_multi_target_node_t *) statement; } else { multi_target = pm_multi_target_node_create(parser); - pm_multi_target_node_targets_append(multi_target, statement); + pm_multi_target_node_targets_append(parser, multi_target, statement); } pm_location_t lparen_loc = PM_LOCATION_TOKEN_VALUE(&opening); @@ -12489,10 +12566,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { multi_target->base.location.end = rparen_loc.end; if (match1(parser, PM_TOKEN_COMMA)) { - return parse_targets_validate(parser, (pm_node_t *) multi_target, PM_BINDING_POWER_INDEX); - } else { - return parse_target_validate(parser, (pm_node_t *) multi_target); + if (binding_power == PM_BINDING_POWER_STATEMENT) { + return parse_targets_validate(parser, (pm_node_t *) multi_target, PM_BINDING_POWER_INDEX); + } + return (pm_node_t *) multi_target; } + + return parse_target_validate(parser, (pm_node_t *) multi_target); } // If we have a single statement and are ending on a right parenthesis @@ -13579,7 +13659,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { parser_lex(parser); pm_token_t for_keyword = parser->previous; pm_node_t *index; + pm_parser_scope_push_transparent(parser); + context_push(parser, PM_CONTEXT_FOR_INDEX); // First, parse out the first index expression. if (accept1(parser, PM_TOKEN_USTAR)) { @@ -13605,6 +13687,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { index = parse_target(parser, index); } + context_pop(parser); pm_parser_scope_pop(parser); pm_do_loop_stack_push(parser, true); @@ -14468,12 +14551,18 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ } // Ensures a call node that is about to become a call operator node does not -// have a block attached. If it does, then we'll need to add an error message -// and destroy the block. Ideally we would keep the node around so that -// consumers would still have access to it, but we don't have a great structure -// for that at the moment. +// have arguments or a block attached. If it does, then we'll need to add an +// error message and destroy the arguments/block. Ideally we would keep the node +// around so that consumers would still have access to it, but we don't have a +// great structure for that at the moment. static void -parse_call_operator_write_block(pm_parser_t *parser, pm_call_node_t *call_node, const pm_token_t *operator) { +parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const pm_token_t *operator) { + if (call_node->arguments != NULL) { + pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_ARGUMENTS); + pm_node_destroy(parser, (pm_node_t *) call_node->arguments); + call_node->arguments = NULL; + } + if (call_node->block != NULL) { pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_BLOCK); pm_node_destroy(parser, (pm_node_t *) call_node->block); @@ -14505,18 +14594,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t return parse_write(parser, node, &token, value); } case PM_SPLAT_NODE: { - pm_splat_node_t *splat_node = (pm_splat_node_t *) node; + pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser); + pm_multi_target_node_targets_append(parser, multi_target, node); - switch (PM_NODE_TYPE(splat_node->expression)) { - case PM_CASE_WRITABLE: - parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); - return parse_write(parser, (pm_node_t *) splat_node, &token, value); - default: - break; - } + parser_lex(parser); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL); + return parse_write(parser, (pm_node_t *) multi_target, &token, value); } - /* fallthrough */ default: parser_lex(parser); @@ -14586,33 +14670,45 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t return result; } case PM_CALL_NODE: { + parser_lex(parser); + pm_call_node_t *cast = (pm_call_node_t *) node; + // If we have a vcall (a method with no arguments and no // receiver that could have been a local variable) then we // will transform it into a local variable write. - if (pm_call_node_variable_call_p((pm_call_node_t *) node)) { - pm_location_t message_loc = ((pm_call_node_t *) node)->message_loc; + if (pm_call_node_variable_call_p(cast)) { + pm_location_t message_loc = cast->message_loc; pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc.start, message_loc.end); if (token_is_numbered_parameter(message_loc.start, message_loc.end)) { pm_parser_err_location(parser, &message_loc, PM_ERR_PARAMETER_NUMBERED_RESERVED); } - parser_lex(parser); pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); - pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, constant_id, 0); + pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0); - pm_node_destroy(parser, node); + pm_node_destroy(parser, (pm_node_t *) cast); return result; } - parser_lex(parser); - node = parse_target(parser, node); + // If there is no call operator and the message is "[]" then + // this is an aref expression, and we can transform it into + // an aset expression. + if (pm_call_node_index_p(cast)) { + pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); + return (pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value); + } - assert(PM_NODE_TYPE_P(node, PM_CALL_NODE)); - parse_call_operator_write_block(parser, (pm_call_node_t *) node, &token); + // If this node cannot be writable, then we have an error. + if (pm_call_node_writable_p(cast)) { + parse_write_name(parser, &cast->name); + } else { + pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_UNEXPECTED); + } + parse_call_operator_write(parser, cast, &token); pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ); - return (pm_node_t *) pm_call_and_write_node_create(parser, (pm_call_node_t *) node, &token, value); + return (pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value); } case PM_MULTI_WRITE_NODE: { parser_lex(parser); @@ -14688,33 +14784,45 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t return result; } case PM_CALL_NODE: { + parser_lex(parser); + pm_call_node_t *cast = (pm_call_node_t *) node; + // If we have a vcall (a method with no arguments and no // receiver that could have been a local variable) then we // will transform it into a local variable write. - if (pm_call_node_variable_call_p((pm_call_node_t *) node)) { - pm_location_t message_loc = ((pm_call_node_t *) node)->message_loc; + if (pm_call_node_variable_call_p(cast)) { + pm_location_t message_loc = cast->message_loc; pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc.start, message_loc.end); if (token_is_numbered_parameter(message_loc.start, message_loc.end)) { pm_parser_err_location(parser, &message_loc, PM_ERR_PARAMETER_NUMBERED_RESERVED); } - parser_lex(parser); pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); - pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, constant_id, 0); + pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0); - pm_node_destroy(parser, node); + pm_node_destroy(parser, (pm_node_t *) cast); return result; } - parser_lex(parser); - node = parse_target(parser, node); + // If there is no call operator and the message is "[]" then + // this is an aref expression, and we can transform it into + // an aset expression. + if (pm_call_node_index_p(cast)) { + pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); + return (pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value); + } - assert(PM_NODE_TYPE_P(node, PM_CALL_NODE)); - parse_call_operator_write_block(parser, (pm_call_node_t *) node, &token); + // If this node cannot be writable, then we have an error. + if (pm_call_node_writable_p(cast)) { + parse_write_name(parser, &cast->name); + } else { + pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_UNEXPECTED); + } + parse_call_operator_write(parser, cast, &token); pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ); - return (pm_node_t *) pm_call_or_write_node_create(parser, (pm_call_node_t *) node, &token, value); + return (pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value); } case PM_MULTI_WRITE_NODE: { parser_lex(parser); @@ -14800,33 +14908,45 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t return result; } case PM_CALL_NODE: { + parser_lex(parser); + pm_call_node_t *cast = (pm_call_node_t *) node; + // If we have a vcall (a method with no arguments and no // receiver that could have been a local variable) then we // will transform it into a local variable write. - if (pm_call_node_variable_call_p((pm_call_node_t *) node)) { - pm_location_t message_loc = ((pm_call_node_t *) node)->message_loc; + if (pm_call_node_variable_call_p(cast)) { + pm_location_t message_loc = cast->message_loc; pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc.start, message_loc.end); if (token_is_numbered_parameter(message_loc.start, message_loc.end)) { pm_parser_err_location(parser, &message_loc, PM_ERR_PARAMETER_NUMBERED_RESERVED); } - parser_lex(parser); pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); - pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, constant_id, 0); + pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0); - pm_node_destroy(parser, node); + pm_node_destroy(parser, (pm_node_t *) cast); return result; } - parser_lex(parser); - node = parse_target(parser, node); + // If there is no call operator and the message is "[]" then + // this is an aref expression, and we can transform it into + // an aset expression. + if (pm_call_node_index_p(cast)) { + pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + return (pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value); + } - assert(PM_NODE_TYPE_P(node, PM_CALL_NODE)); - parse_call_operator_write_block(parser, (pm_call_node_t *) node, &token); + // If this node cannot be writable, then we have an error. + if (pm_call_node_writable_p(cast)) { + parse_write_name(parser, &cast->name); + } else { + pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_UNEXPECTED); + } + parse_call_operator_write(parser, cast, &token); pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); - return (pm_node_t *) pm_call_operator_write_node_create(parser, (pm_call_node_t *) node, &token, value); + return (pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value); } case PM_MULTI_WRITE_NODE: { parser_lex(parser); @@ -14879,15 +14999,31 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_string_list_t named_captures; pm_string_list_init(&named_captures); - const pm_location_t *content_loc = &((pm_regular_expression_node_t *) node)->content_loc; - if (pm_regexp_named_capture_group_names(content_loc->start, (size_t) (content_loc->end - content_loc->start), &named_captures, parser->encoding_changed, &parser->encoding) && (named_captures.length > 0)) { + const pm_string_t *unescaped = &((pm_regular_expression_node_t *) node)->unescaped; + if (pm_regexp_named_capture_group_names(pm_string_source(unescaped), pm_string_length(unescaped), &named_captures, parser->encoding_changed, &parser->encoding) && (named_captures.length > 0)) { pm_match_write_node_t *match = pm_match_write_node_create(parser, call); for (size_t index = 0; index < named_captures.length; index++) { pm_string_t *name = &named_captures.strings[index]; - assert(name->type == PM_STRING_SHARED); + pm_constant_id_t local; + + if (unescaped->type == PM_STRING_SHARED) { + // If the unescaped string is a slice of the source, + // then we can copy the names directly. The pointers + // will line up. + local = pm_parser_local_add_location(parser, name->source, name->source + name->length); + } else { + // Otherwise, the name is a slice of the malloc-ed + // owned string, in which case we need to copy it + // out into a new string. + size_t length = pm_string_length(name); + + void *memory = malloc(length); + memcpy(memory, pm_string_source(name), length); + + local = pm_parser_local_add_owned(parser, (const uint8_t *) memory, length); + } - pm_constant_id_t local = pm_parser_local_add_location(parser, name->source, name->source + name->length); pm_constant_id_list_append(&match->locals, local); } @@ -15502,14 +15638,14 @@ pm_parse(pm_parser_t *parser) { PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { - pm_buffer_append_str(buffer, "PRISM", 5); - pm_buffer_append_u8(buffer, PRISM_VERSION_MAJOR); - pm_buffer_append_u8(buffer, PRISM_VERSION_MINOR); - pm_buffer_append_u8(buffer, PRISM_VERSION_PATCH); - pm_buffer_append_u8(buffer, PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS ? 1 : 0); + pm_buffer_append_string(buffer, "PRISM", 5); + pm_buffer_append_byte(buffer, PRISM_VERSION_MAJOR); + pm_buffer_append_byte(buffer, PRISM_VERSION_MINOR); + pm_buffer_append_byte(buffer, PRISM_VERSION_PATCH); + pm_buffer_append_byte(buffer, PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS ? 1 : 0); pm_serialize_content(parser, node, buffer); - pm_buffer_append_str(buffer, "\0", 1); + pm_buffer_append_string(buffer, "\0", 1); } // Parse and serialize the AST represented by the given source to the given diff --git a/src/main/c/yarp/src/serialize.c b/src/main/c/yarp/src/serialize.c index beb55fb7e247..f53fe5f5f5ff 100644 --- a/src/main/c/yarp/src/serialize.c +++ b/src/main/c/yarp/src/serialize.c @@ -27,24 +27,24 @@ pm_serialize_location(pm_parser_t *parser, pm_location_t *location, pm_buffer_t assert(location->end); assert(location->start <= location->end); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(location->start - parser->start)); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(location->end - location->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(location->start - parser->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(location->end - location->start)); } static void pm_serialize_string(pm_parser_t *parser, pm_string_t *string, pm_buffer_t *buffer) { switch (string->type) { case PM_STRING_SHARED: { - pm_buffer_append_u8(buffer, 1); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(pm_string_source(string) - parser->start)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(pm_string_length(string))); + pm_buffer_append_byte(buffer, 1); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(pm_string_source(string) - parser->start)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(pm_string_length(string))); break; } case PM_STRING_OWNED: case PM_STRING_CONSTANT: { uint32_t length = pm_sizet_to_u32(pm_string_length(string)); - pm_buffer_append_u8(buffer, 2); - pm_buffer_append_u32(buffer, length); + pm_buffer_append_byte(buffer, 2); + pm_buffer_append_varint(buffer, length); pm_buffer_append_bytes(buffer, pm_string_source(string), length); break; } @@ -56,7 +56,7 @@ pm_serialize_string(pm_parser_t *parser, pm_string_t *string, pm_buffer_t *buffe void pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { - pm_buffer_append_u8(buffer, (uint8_t) PM_NODE_TYPE(node)); + pm_buffer_append_byte(buffer, (uint8_t) PM_NODE_TYPE(node)); size_t offset = buffer->length; @@ -89,15 +89,16 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_ARGUMENTS_NODE: { uint32_t arguments_size = pm_sizet_to_u32(((pm_arguments_node_t *)node)->arguments.size); - pm_buffer_append_u32(buffer, arguments_size); + pm_buffer_append_varint(buffer, arguments_size); for (uint32_t index = 0; index < arguments_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_arguments_node_t *)node)->arguments.nodes[index], buffer); } + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_ARRAY_NODE: { uint32_t elements_size = pm_sizet_to_u32(((pm_array_node_t *)node)->elements.size); - pm_buffer_append_u32(buffer, elements_size); + pm_buffer_append_varint(buffer, elements_size); for (uint32_t index = 0; index < elements_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_array_node_t *)node)->elements.nodes[index], buffer); } @@ -105,22 +106,22 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_ARRAY_PATTERN_NODE: { if (((pm_array_pattern_node_t *)node)->constant == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_array_pattern_node_t *)node)->constant, buffer); } uint32_t requireds_size = pm_sizet_to_u32(((pm_array_pattern_node_t *)node)->requireds.size); - pm_buffer_append_u32(buffer, requireds_size); + pm_buffer_append_varint(buffer, requireds_size); for (uint32_t index = 0; index < requireds_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_array_pattern_node_t *)node)->requireds.nodes[index], buffer); } if (((pm_array_pattern_node_t *)node)->rest == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_array_pattern_node_t *)node)->rest, buffer); } uint32_t posts_size = pm_sizet_to_u32(((pm_array_pattern_node_t *)node)->posts.size); - pm_buffer_append_u32(buffer, posts_size); + pm_buffer_append_varint(buffer, posts_size); for (uint32_t index = 0; index < posts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_array_pattern_node_t *)node)->posts.nodes[index], buffer); } @@ -129,7 +130,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_ASSOC_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_assoc_node_t *)node)->key, buffer); if (((pm_assoc_node_t *)node)->value == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_assoc_node_t *)node)->value, buffer); } @@ -137,34 +138,34 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_ASSOC_SPLAT_NODE: { if (((pm_assoc_splat_node_t *)node)->value == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_assoc_splat_node_t *)node)->value, buffer); } break; } case PM_BACK_REFERENCE_READ_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_back_reference_read_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_back_reference_read_node_t *)node)->name)); break; } case PM_BEGIN_NODE: { if (((pm_begin_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_begin_node_t *)node)->statements, buffer); } if (((pm_begin_node_t *)node)->rescue_clause == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_begin_node_t *)node)->rescue_clause, buffer); } if (((pm_begin_node_t *)node)->else_clause == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_begin_node_t *)node)->else_clause, buffer); } if (((pm_begin_node_t *)node)->ensure_clause == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_begin_node_t *)node)->ensure_clause, buffer); } @@ -172,46 +173,46 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_BLOCK_ARGUMENT_NODE: { if (((pm_block_argument_node_t *)node)->expression == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_block_argument_node_t *)node)->expression, buffer); } break; } case PM_BLOCK_LOCAL_VARIABLE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_block_local_variable_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_block_local_variable_node_t *)node)->name)); break; } case PM_BLOCK_NODE: { uint32_t locals_size = pm_sizet_to_u32(((pm_block_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_block_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_block_node_t *)node)->locals.ids[index])); } if (((pm_block_node_t *)node)->parameters == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_block_node_t *)node)->parameters, buffer); } if (((pm_block_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_block_node_t *)node)->body, buffer); } break; } case PM_BLOCK_PARAMETER_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_block_parameter_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_block_parameter_node_t *)node)->name)); break; } case PM_BLOCK_PARAMETERS_NODE: { if (((pm_block_parameters_node_t *)node)->parameters == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_block_parameters_node_t *)node)->parameters, buffer); } uint32_t locals_size = pm_sizet_to_u32(((pm_block_parameters_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_block_parameters_node_t *)node)->locals.nodes[index], buffer); } @@ -219,7 +220,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_BREAK_NODE: { if (((pm_break_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_break_node_t *)node)->arguments, buffer); } @@ -227,73 +228,58 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_CALL_AND_WRITE_NODE: { if (((pm_call_and_write_node_t *)node)->receiver == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_call_and_write_node_t *)node)->receiver, buffer); } - if (((pm_call_and_write_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); - } else { - pm_serialize_node(parser, (pm_node_t *)((pm_call_and_write_node_t *)node)->arguments, buffer); - } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_and_write_node_t *)node)->read_name)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_and_write_node_t *)node)->write_name)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_and_write_node_t *)node)->read_name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_and_write_node_t *)node)->write_name)); pm_serialize_node(parser, (pm_node_t *)((pm_call_and_write_node_t *)node)->value, buffer); break; } case PM_CALL_NODE: { if (((pm_call_node_t *)node)->receiver == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_call_node_t *)node)->receiver, buffer); } if (((pm_call_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_call_node_t *)node)->arguments, buffer); } if (((pm_call_node_t *)node)->block == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_call_node_t *)node)->block, buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_node_t *)node)->name)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_node_t *)node)->name)); break; } case PM_CALL_OPERATOR_WRITE_NODE: { if (((pm_call_operator_write_node_t *)node)->receiver == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_call_operator_write_node_t *)node)->receiver, buffer); } - if (((pm_call_operator_write_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); - } else { - pm_serialize_node(parser, (pm_node_t *)((pm_call_operator_write_node_t *)node)->arguments, buffer); - } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_operator_write_node_t *)node)->read_name)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_operator_write_node_t *)node)->write_name)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_operator_write_node_t *)node)->read_name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_operator_write_node_t *)node)->write_name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_operator_write_node_t *)node)->operator)); pm_serialize_node(parser, (pm_node_t *)((pm_call_operator_write_node_t *)node)->value, buffer); break; } case PM_CALL_OR_WRITE_NODE: { if (((pm_call_or_write_node_t *)node)->receiver == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_call_or_write_node_t *)node)->receiver, buffer); } - if (((pm_call_or_write_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); - } else { - pm_serialize_node(parser, (pm_node_t *)((pm_call_or_write_node_t *)node)->arguments, buffer); - } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_or_write_node_t *)node)->read_name)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_call_or_write_node_t *)node)->write_name)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_or_write_node_t *)node)->read_name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_call_or_write_node_t *)node)->write_name)); pm_serialize_node(parser, (pm_node_t *)((pm_call_or_write_node_t *)node)->value, buffer); break; } @@ -304,17 +290,17 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_CASE_NODE: { if (((pm_case_node_t *)node)->predicate == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_case_node_t *)node)->predicate, buffer); } uint32_t conditions_size = pm_sizet_to_u32(((pm_case_node_t *)node)->conditions.size); - pm_buffer_append_u32(buffer, conditions_size); + pm_buffer_append_varint(buffer, conditions_size); for (uint32_t index = 0; index < conditions_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_case_node_t *)node)->conditions.nodes[index], buffer); } if (((pm_case_node_t *)node)->consequent == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_case_node_t *)node)->consequent, buffer); } @@ -322,66 +308,66 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_CLASS_NODE: { uint32_t locals_size = pm_sizet_to_u32(((pm_class_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_node_t *)node)->locals.ids[index])); } pm_serialize_node(parser, (pm_node_t *)((pm_class_node_t *)node)->constant_path, buffer); if (((pm_class_node_t *)node)->superclass == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_class_node_t *)node)->superclass, buffer); } if (((pm_class_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_class_node_t *)node)->body, buffer); } - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_node_t *)node)->name)); break; } case PM_CLASS_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_and_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_and_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_class_variable_and_write_node_t *)node)->value, buffer); break; } case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_operator_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_operator_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_class_variable_operator_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_operator_write_node_t *)node)->operator)); break; } case PM_CLASS_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_or_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_or_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_class_variable_or_write_node_t *)node)->value, buffer); break; } case PM_CLASS_VARIABLE_READ_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_read_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_read_node_t *)node)->name)); break; } case PM_CLASS_VARIABLE_TARGET_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_target_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_target_node_t *)node)->name)); break; } case PM_CLASS_VARIABLE_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_class_variable_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_class_variable_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_class_variable_write_node_t *)node)->value, buffer); break; } case PM_CONSTANT_AND_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_and_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_and_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_constant_and_write_node_t *)node)->value, buffer); break; } case PM_CONSTANT_OPERATOR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_operator_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_operator_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_constant_operator_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_operator_write_node_t *)node)->operator)); break; } case PM_CONSTANT_OR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_or_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_or_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_constant_or_write_node_t *)node)->value, buffer); break; } @@ -392,7 +378,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_CONSTANT_PATH_NODE: { if (((pm_constant_path_node_t *)node)->parent == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_node_t *)node)->parent, buffer); } @@ -402,7 +388,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_operator_write_node_t *)node)->target, buffer); pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_operator_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_path_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_path_operator_write_node_t *)node)->operator)); break; } case PM_CONSTANT_PATH_OR_WRITE_NODE: { @@ -412,7 +398,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_CONSTANT_PATH_TARGET_NODE: { if (((pm_constant_path_target_node_t *)node)->parent == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_constant_path_target_node_t *)node)->parent, buffer); } @@ -425,15 +411,15 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { break; } case PM_CONSTANT_READ_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_read_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_read_node_t *)node)->name)); break; } case PM_CONSTANT_TARGET_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_target_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_target_node_t *)node)->name)); break; } case PM_CONSTANT_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_constant_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_constant_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_constant_write_node_t *)node)->value, buffer); break; } @@ -441,27 +427,27 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { // serialize length // encoding of location u32s make us need to save this offset. size_t length_offset = buffer->length; - pm_buffer_append_str(buffer, "\0\0\0\0", 4); /* consume 4 bytes, updated below */ - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_def_node_t *)node)->name)); + pm_buffer_append_string(buffer, "\0\0\0\0", 4); /* consume 4 bytes, updated below */ + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_def_node_t *)node)->name)); if (((pm_def_node_t *)node)->receiver == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_def_node_t *)node)->receiver, buffer); } if (((pm_def_node_t *)node)->parameters == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_def_node_t *)node)->parameters, buffer); } if (((pm_def_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_def_node_t *)node)->body, buffer); } uint32_t locals_size = pm_sizet_to_u32(((pm_def_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_def_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_def_node_t *)node)->locals.ids[index])); } // serialize length uint32_t length = pm_sizet_to_u32(buffer->length - offset - sizeof(uint32_t)); @@ -474,7 +460,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_ELSE_NODE: { if (((pm_else_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_else_node_t *)node)->statements, buffer); } @@ -482,7 +468,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_EMBEDDED_STATEMENTS_NODE: { if (((pm_embedded_statements_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_embedded_statements_node_t *)node)->statements, buffer); } @@ -494,7 +480,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_ENSURE_NODE: { if (((pm_ensure_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_ensure_node_t *)node)->statements, buffer); } @@ -505,13 +491,13 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_FIND_PATTERN_NODE: { if (((pm_find_pattern_node_t *)node)->constant == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_find_pattern_node_t *)node)->constant, buffer); } pm_serialize_node(parser, (pm_node_t *)((pm_find_pattern_node_t *)node)->left, buffer); uint32_t requireds_size = pm_sizet_to_u32(((pm_find_pattern_node_t *)node)->requireds.size); - pm_buffer_append_u32(buffer, requireds_size); + pm_buffer_append_varint(buffer, requireds_size); for (uint32_t index = 0; index < requireds_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_find_pattern_node_t *)node)->requireds.nodes[index], buffer); } @@ -520,16 +506,16 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_FLIP_FLOP_NODE: { if (((pm_flip_flop_node_t *)node)->left == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_flip_flop_node_t *)node)->left, buffer); } if (((pm_flip_flop_node_t *)node)->right == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_flip_flop_node_t *)node)->right, buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_FLOAT_NODE: { @@ -539,7 +525,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_serialize_node(parser, (pm_node_t *)((pm_for_node_t *)node)->index, buffer); pm_serialize_node(parser, (pm_node_t *)((pm_for_node_t *)node)->collection, buffer); if (((pm_for_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_for_node_t *)node)->statements, buffer); } @@ -553,44 +539,44 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_FORWARDING_SUPER_NODE: { if (((pm_forwarding_super_node_t *)node)->block == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_forwarding_super_node_t *)node)->block, buffer); } break; } case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_and_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_and_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_global_variable_and_write_node_t *)node)->value, buffer); break; } case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_operator_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_operator_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_global_variable_operator_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_operator_write_node_t *)node)->operator)); break; } case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_or_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_or_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_global_variable_or_write_node_t *)node)->value, buffer); break; } case PM_GLOBAL_VARIABLE_READ_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_read_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_read_node_t *)node)->name)); break; } case PM_GLOBAL_VARIABLE_TARGET_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_target_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_target_node_t *)node)->name)); break; } case PM_GLOBAL_VARIABLE_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_global_variable_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_global_variable_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_global_variable_write_node_t *)node)->value, buffer); break; } case PM_HASH_NODE: { uint32_t elements_size = pm_sizet_to_u32(((pm_hash_node_t *)node)->elements.size); - pm_buffer_append_u32(buffer, elements_size); + pm_buffer_append_varint(buffer, elements_size); for (uint32_t index = 0; index < elements_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_hash_node_t *)node)->elements.nodes[index], buffer); } @@ -598,31 +584,31 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_HASH_PATTERN_NODE: { if (((pm_hash_pattern_node_t *)node)->constant == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_hash_pattern_node_t *)node)->constant, buffer); } - uint32_t assocs_size = pm_sizet_to_u32(((pm_hash_pattern_node_t *)node)->assocs.size); - pm_buffer_append_u32(buffer, assocs_size); - for (uint32_t index = 0; index < assocs_size; index++) { - pm_serialize_node(parser, (pm_node_t *) ((pm_hash_pattern_node_t *)node)->assocs.nodes[index], buffer); + uint32_t elements_size = pm_sizet_to_u32(((pm_hash_pattern_node_t *)node)->elements.size); + pm_buffer_append_varint(buffer, elements_size); + for (uint32_t index = 0; index < elements_size; index++) { + pm_serialize_node(parser, (pm_node_t *) ((pm_hash_pattern_node_t *)node)->elements.nodes[index], buffer); } - if (((pm_hash_pattern_node_t *)node)->kwrest == NULL) { - pm_buffer_append_u8(buffer, 0); + if (((pm_hash_pattern_node_t *)node)->rest == NULL) { + pm_buffer_append_byte(buffer, 0); } else { - pm_serialize_node(parser, (pm_node_t *)((pm_hash_pattern_node_t *)node)->kwrest, buffer); + pm_serialize_node(parser, (pm_node_t *)((pm_hash_pattern_node_t *)node)->rest, buffer); } break; } case PM_IF_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_if_node_t *)node)->predicate, buffer); if (((pm_if_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_if_node_t *)node)->statements, buffer); } if (((pm_if_node_t *)node)->consequent == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_if_node_t *)node)->consequent, buffer); } @@ -639,66 +625,127 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_IN_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_in_node_t *)node)->pattern, buffer); if (((pm_in_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_in_node_t *)node)->statements, buffer); } break; } + case PM_INDEX_AND_WRITE_NODE: { + if (((pm_index_and_write_node_t *)node)->receiver == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_and_write_node_t *)node)->receiver, buffer); + } + if (((pm_index_and_write_node_t *)node)->arguments == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_and_write_node_t *)node)->arguments, buffer); + } + if (((pm_index_and_write_node_t *)node)->block == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_and_write_node_t *)node)->block, buffer); + } + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_serialize_node(parser, (pm_node_t *)((pm_index_and_write_node_t *)node)->value, buffer); + break; + } + case PM_INDEX_OPERATOR_WRITE_NODE: { + if (((pm_index_operator_write_node_t *)node)->receiver == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_operator_write_node_t *)node)->receiver, buffer); + } + if (((pm_index_operator_write_node_t *)node)->arguments == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_operator_write_node_t *)node)->arguments, buffer); + } + if (((pm_index_operator_write_node_t *)node)->block == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_operator_write_node_t *)node)->block, buffer); + } + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_index_operator_write_node_t *)node)->operator)); + pm_serialize_node(parser, (pm_node_t *)((pm_index_operator_write_node_t *)node)->value, buffer); + break; + } + case PM_INDEX_OR_WRITE_NODE: { + if (((pm_index_or_write_node_t *)node)->receiver == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_or_write_node_t *)node)->receiver, buffer); + } + if (((pm_index_or_write_node_t *)node)->arguments == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_or_write_node_t *)node)->arguments, buffer); + } + if (((pm_index_or_write_node_t *)node)->block == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_index_or_write_node_t *)node)->block, buffer); + } + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_serialize_node(parser, (pm_node_t *)((pm_index_or_write_node_t *)node)->value, buffer); + break; + } case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_and_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_and_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_instance_variable_and_write_node_t *)node)->value, buffer); break; } case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_operator_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_operator_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_instance_variable_operator_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_operator_write_node_t *)node)->operator)); break; } case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_or_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_or_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_instance_variable_or_write_node_t *)node)->value, buffer); break; } case PM_INSTANCE_VARIABLE_READ_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_read_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_read_node_t *)node)->name)); break; } case PM_INSTANCE_VARIABLE_TARGET_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_target_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_target_node_t *)node)->name)); break; } case PM_INSTANCE_VARIABLE_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_instance_variable_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_instance_variable_write_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_instance_variable_write_node_t *)node)->value, buffer); break; } case PM_INTEGER_NODE: { - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: { uint32_t parts_size = pm_sizet_to_u32(((pm_interpolated_match_last_line_node_t *)node)->parts.size); - pm_buffer_append_u32(buffer, parts_size); + pm_buffer_append_varint(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_interpolated_match_last_line_node_t *)node)->parts.nodes[index], buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { uint32_t parts_size = pm_sizet_to_u32(((pm_interpolated_regular_expression_node_t *)node)->parts.size); - pm_buffer_append_u32(buffer, parts_size); + pm_buffer_append_varint(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_interpolated_regular_expression_node_t *)node)->parts.nodes[index], buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_INTERPOLATED_STRING_NODE: { uint32_t parts_size = pm_sizet_to_u32(((pm_interpolated_string_node_t *)node)->parts.size); - pm_buffer_append_u32(buffer, parts_size); + pm_buffer_append_varint(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_interpolated_string_node_t *)node)->parts.nodes[index], buffer); } @@ -706,7 +753,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_INTERPOLATED_SYMBOL_NODE: { uint32_t parts_size = pm_sizet_to_u32(((pm_interpolated_symbol_node_t *)node)->parts.size); - pm_buffer_append_u32(buffer, parts_size); + pm_buffer_append_varint(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_interpolated_symbol_node_t *)node)->parts.nodes[index], buffer); } @@ -714,7 +761,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_INTERPOLATED_X_STRING_NODE: { uint32_t parts_size = pm_sizet_to_u32(((pm_interpolated_x_string_node_t *)node)->parts.size); - pm_buffer_append_u32(buffer, parts_size); + pm_buffer_append_varint(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_interpolated_x_string_node_t *)node)->parts.nodes[index], buffer); } @@ -722,38 +769,38 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_KEYWORD_HASH_NODE: { uint32_t elements_size = pm_sizet_to_u32(((pm_keyword_hash_node_t *)node)->elements.size); - pm_buffer_append_u32(buffer, elements_size); + pm_buffer_append_varint(buffer, elements_size); for (uint32_t index = 0; index < elements_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_keyword_hash_node_t *)node)->elements.nodes[index], buffer); } break; } case PM_KEYWORD_PARAMETER_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_keyword_parameter_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_keyword_parameter_node_t *)node)->name)); if (((pm_keyword_parameter_node_t *)node)->value == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_keyword_parameter_node_t *)node)->value, buffer); } break; } case PM_KEYWORD_REST_PARAMETER_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_keyword_rest_parameter_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_keyword_rest_parameter_node_t *)node)->name)); break; } case PM_LAMBDA_NODE: { uint32_t locals_size = pm_sizet_to_u32(((pm_lambda_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_lambda_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_lambda_node_t *)node)->locals.ids[index])); } if (((pm_lambda_node_t *)node)->parameters == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_lambda_node_t *)node)->parameters, buffer); } if (((pm_lambda_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_lambda_node_t *)node)->body, buffer); } @@ -761,42 +808,42 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_LOCAL_VARIABLE_AND_WRITE_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_local_variable_and_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_and_write_node_t *)node)->name)); - pm_buffer_append_u32(buffer, ((pm_local_variable_and_write_node_t *)node)->depth); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_and_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, ((pm_local_variable_and_write_node_t *)node)->depth); break; } case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_local_variable_operator_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_operator_write_node_t *)node)->name)); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_operator_write_node_t *)node)->operator)); - pm_buffer_append_u32(buffer, ((pm_local_variable_operator_write_node_t *)node)->depth); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_operator_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_operator_write_node_t *)node)->operator)); + pm_buffer_append_varint(buffer, ((pm_local_variable_operator_write_node_t *)node)->depth); break; } case PM_LOCAL_VARIABLE_OR_WRITE_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_local_variable_or_write_node_t *)node)->value, buffer); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_or_write_node_t *)node)->name)); - pm_buffer_append_u32(buffer, ((pm_local_variable_or_write_node_t *)node)->depth); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_or_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, ((pm_local_variable_or_write_node_t *)node)->depth); break; } case PM_LOCAL_VARIABLE_READ_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_read_node_t *)node)->name)); - pm_buffer_append_u32(buffer, ((pm_local_variable_read_node_t *)node)->depth); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_read_node_t *)node)->name)); + pm_buffer_append_varint(buffer, ((pm_local_variable_read_node_t *)node)->depth); break; } case PM_LOCAL_VARIABLE_TARGET_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_target_node_t *)node)->name)); - pm_buffer_append_u32(buffer, ((pm_local_variable_target_node_t *)node)->depth); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_target_node_t *)node)->name)); + pm_buffer_append_varint(buffer, ((pm_local_variable_target_node_t *)node)->depth); break; } case PM_LOCAL_VARIABLE_WRITE_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_local_variable_write_node_t *)node)->name)); - pm_buffer_append_u32(buffer, ((pm_local_variable_write_node_t *)node)->depth); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_local_variable_write_node_t *)node)->name)); + pm_buffer_append_varint(buffer, ((pm_local_variable_write_node_t *)node)->depth); pm_serialize_node(parser, (pm_node_t *)((pm_local_variable_write_node_t *)node)->value, buffer); break; } case PM_MATCH_LAST_LINE_NODE: { pm_serialize_string(parser, &((pm_match_last_line_node_t *)node)->unescaped, buffer); - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_MATCH_PREDICATE_NODE: { @@ -812,9 +859,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_MATCH_WRITE_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_match_write_node_t *)node)->call, buffer); uint32_t locals_size = pm_sizet_to_u32(((pm_match_write_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_match_write_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_match_write_node_t *)node)->locals.ids[index])); } break; } @@ -823,39 +870,59 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_MODULE_NODE: { uint32_t locals_size = pm_sizet_to_u32(((pm_module_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_module_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_module_node_t *)node)->locals.ids[index])); } pm_serialize_node(parser, (pm_node_t *)((pm_module_node_t *)node)->constant_path, buffer); if (((pm_module_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_module_node_t *)node)->body, buffer); } - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_module_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_module_node_t *)node)->name)); break; } case PM_MULTI_TARGET_NODE: { - uint32_t targets_size = pm_sizet_to_u32(((pm_multi_target_node_t *)node)->targets.size); - pm_buffer_append_u32(buffer, targets_size); - for (uint32_t index = 0; index < targets_size; index++) { - pm_serialize_node(parser, (pm_node_t *) ((pm_multi_target_node_t *)node)->targets.nodes[index], buffer); + uint32_t lefts_size = pm_sizet_to_u32(((pm_multi_target_node_t *)node)->lefts.size); + pm_buffer_append_varint(buffer, lefts_size); + for (uint32_t index = 0; index < lefts_size; index++) { + pm_serialize_node(parser, (pm_node_t *) ((pm_multi_target_node_t *)node)->lefts.nodes[index], buffer); + } + if (((pm_multi_target_node_t *)node)->rest == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_multi_target_node_t *)node)->rest, buffer); + } + uint32_t rights_size = pm_sizet_to_u32(((pm_multi_target_node_t *)node)->rights.size); + pm_buffer_append_varint(buffer, rights_size); + for (uint32_t index = 0; index < rights_size; index++) { + pm_serialize_node(parser, (pm_node_t *) ((pm_multi_target_node_t *)node)->rights.nodes[index], buffer); } break; } case PM_MULTI_WRITE_NODE: { - uint32_t targets_size = pm_sizet_to_u32(((pm_multi_write_node_t *)node)->targets.size); - pm_buffer_append_u32(buffer, targets_size); - for (uint32_t index = 0; index < targets_size; index++) { - pm_serialize_node(parser, (pm_node_t *) ((pm_multi_write_node_t *)node)->targets.nodes[index], buffer); + uint32_t lefts_size = pm_sizet_to_u32(((pm_multi_write_node_t *)node)->lefts.size); + pm_buffer_append_varint(buffer, lefts_size); + for (uint32_t index = 0; index < lefts_size; index++) { + pm_serialize_node(parser, (pm_node_t *) ((pm_multi_write_node_t *)node)->lefts.nodes[index], buffer); + } + if (((pm_multi_write_node_t *)node)->rest == NULL) { + pm_buffer_append_byte(buffer, 0); + } else { + pm_serialize_node(parser, (pm_node_t *)((pm_multi_write_node_t *)node)->rest, buffer); + } + uint32_t rights_size = pm_sizet_to_u32(((pm_multi_write_node_t *)node)->rights.size); + pm_buffer_append_varint(buffer, rights_size); + for (uint32_t index = 0; index < rights_size; index++) { + pm_serialize_node(parser, (pm_node_t *) ((pm_multi_write_node_t *)node)->rights.nodes[index], buffer); } pm_serialize_node(parser, (pm_node_t *)((pm_multi_write_node_t *)node)->value, buffer); break; } case PM_NEXT_NODE: { if (((pm_next_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_next_node_t *)node)->arguments, buffer); } @@ -868,11 +935,11 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { break; } case PM_NUMBERED_REFERENCE_READ_NODE: { - pm_buffer_append_u32(buffer, ((pm_numbered_reference_read_node_t *)node)->number); + pm_buffer_append_varint(buffer, ((pm_numbered_reference_read_node_t *)node)->number); break; } case PM_OPTIONAL_PARAMETER_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_optional_parameter_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_optional_parameter_node_t *)node)->name)); pm_serialize_node(parser, (pm_node_t *)((pm_optional_parameter_node_t *)node)->value, buffer); break; } @@ -883,37 +950,37 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_PARAMETERS_NODE: { uint32_t requireds_size = pm_sizet_to_u32(((pm_parameters_node_t *)node)->requireds.size); - pm_buffer_append_u32(buffer, requireds_size); + pm_buffer_append_varint(buffer, requireds_size); for (uint32_t index = 0; index < requireds_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_parameters_node_t *)node)->requireds.nodes[index], buffer); } uint32_t optionals_size = pm_sizet_to_u32(((pm_parameters_node_t *)node)->optionals.size); - pm_buffer_append_u32(buffer, optionals_size); + pm_buffer_append_varint(buffer, optionals_size); for (uint32_t index = 0; index < optionals_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_parameters_node_t *)node)->optionals.nodes[index], buffer); } if (((pm_parameters_node_t *)node)->rest == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_parameters_node_t *)node)->rest, buffer); } uint32_t posts_size = pm_sizet_to_u32(((pm_parameters_node_t *)node)->posts.size); - pm_buffer_append_u32(buffer, posts_size); + pm_buffer_append_varint(buffer, posts_size); for (uint32_t index = 0; index < posts_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_parameters_node_t *)node)->posts.nodes[index], buffer); } uint32_t keywords_size = pm_sizet_to_u32(((pm_parameters_node_t *)node)->keywords.size); - pm_buffer_append_u32(buffer, keywords_size); + pm_buffer_append_varint(buffer, keywords_size); for (uint32_t index = 0; index < keywords_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_parameters_node_t *)node)->keywords.nodes[index], buffer); } if (((pm_parameters_node_t *)node)->keyword_rest == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_parameters_node_t *)node)->keyword_rest, buffer); } if (((pm_parameters_node_t *)node)->block == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_parameters_node_t *)node)->block, buffer); } @@ -921,7 +988,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_PARENTHESES_NODE: { if (((pm_parentheses_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_parentheses_node_t *)node)->body, buffer); } @@ -937,7 +1004,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_POST_EXECUTION_NODE: { if (((pm_post_execution_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_post_execution_node_t *)node)->statements, buffer); } @@ -945,7 +1012,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_PRE_EXECUTION_NODE: { if (((pm_pre_execution_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_pre_execution_node_t *)node)->statements, buffer); } @@ -953,25 +1020,25 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_PROGRAM_NODE: { uint32_t locals_size = pm_sizet_to_u32(((pm_program_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_program_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_program_node_t *)node)->locals.ids[index])); } pm_serialize_node(parser, (pm_node_t *)((pm_program_node_t *)node)->statements, buffer); break; } case PM_RANGE_NODE: { if (((pm_range_node_t *)node)->left == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_range_node_t *)node)->left, buffer); } if (((pm_range_node_t *)node)->right == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_range_node_t *)node)->right, buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_RATIONAL_NODE: { @@ -983,19 +1050,11 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_REGULAR_EXPRESSION_NODE: { pm_serialize_string(parser, &((pm_regular_expression_node_t *)node)->unescaped, buffer); - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); - break; - } - case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { - uint32_t parameters_size = pm_sizet_to_u32(((pm_required_destructured_parameter_node_t *)node)->parameters.size); - pm_buffer_append_u32(buffer, parameters_size); - for (uint32_t index = 0; index < parameters_size; index++) { - pm_serialize_node(parser, (pm_node_t *) ((pm_required_destructured_parameter_node_t *)node)->parameters.nodes[index], buffer); - } + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_REQUIRED_PARAMETER_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_required_parameter_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_required_parameter_node_t *)node)->name)); break; } case PM_RESCUE_MODIFIER_NODE: { @@ -1005,29 +1064,29 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_RESCUE_NODE: { uint32_t exceptions_size = pm_sizet_to_u32(((pm_rescue_node_t *)node)->exceptions.size); - pm_buffer_append_u32(buffer, exceptions_size); + pm_buffer_append_varint(buffer, exceptions_size); for (uint32_t index = 0; index < exceptions_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_rescue_node_t *)node)->exceptions.nodes[index], buffer); } if (((pm_rescue_node_t *)node)->reference == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_rescue_node_t *)node)->reference, buffer); } if (((pm_rescue_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_rescue_node_t *)node)->statements, buffer); } if (((pm_rescue_node_t *)node)->consequent == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_rescue_node_t *)node)->consequent, buffer); } break; } case PM_REST_PARAMETER_NODE: { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_rest_parameter_node_t *)node)->name)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_rest_parameter_node_t *)node)->name)); break; } case PM_RETRY_NODE: { @@ -1035,7 +1094,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_RETURN_NODE: { if (((pm_return_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_return_node_t *)node)->arguments, buffer); } @@ -1046,13 +1105,13 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_SINGLETON_CLASS_NODE: { uint32_t locals_size = pm_sizet_to_u32(((pm_singleton_class_node_t *)node)->locals.size); - pm_buffer_append_u32(buffer, locals_size); + pm_buffer_append_varint(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(((pm_singleton_class_node_t *)node)->locals.ids[index])); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(((pm_singleton_class_node_t *)node)->locals.ids[index])); } pm_serialize_node(parser, (pm_node_t *)((pm_singleton_class_node_t *)node)->expression, buffer); if (((pm_singleton_class_node_t *)node)->body == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_singleton_class_node_t *)node)->body, buffer); } @@ -1070,7 +1129,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_SPLAT_NODE: { if (((pm_splat_node_t *)node)->expression == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_splat_node_t *)node)->expression, buffer); } @@ -1078,7 +1137,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_STATEMENTS_NODE: { uint32_t body_size = pm_sizet_to_u32(((pm_statements_node_t *)node)->body.size); - pm_buffer_append_u32(buffer, body_size); + pm_buffer_append_varint(buffer, body_size); for (uint32_t index = 0; index < body_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_statements_node_t *)node)->body.nodes[index], buffer); } @@ -1090,18 +1149,18 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { break; } case PM_STRING_NODE: { - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); pm_serialize_string(parser, &((pm_string_node_t *)node)->unescaped, buffer); break; } case PM_SUPER_NODE: { if (((pm_super_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_super_node_t *)node)->arguments, buffer); } if (((pm_super_node_t *)node)->block == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_super_node_t *)node)->block, buffer); } @@ -1116,7 +1175,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_UNDEF_NODE: { uint32_t names_size = pm_sizet_to_u32(((pm_undef_node_t *)node)->names.size); - pm_buffer_append_u32(buffer, names_size); + pm_buffer_append_varint(buffer, names_size); for (uint32_t index = 0; index < names_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_undef_node_t *)node)->names.nodes[index], buffer); } @@ -1125,12 +1184,12 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_UNLESS_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_unless_node_t *)node)->predicate, buffer); if (((pm_unless_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_unless_node_t *)node)->statements, buffer); } if (((pm_unless_node_t *)node)->consequent == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_unless_node_t *)node)->consequent, buffer); } @@ -1139,21 +1198,21 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_UNTIL_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_until_node_t *)node)->predicate, buffer); if (((pm_until_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_until_node_t *)node)->statements, buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_WHEN_NODE: { uint32_t conditions_size = pm_sizet_to_u32(((pm_when_node_t *)node)->conditions.size); - pm_buffer_append_u32(buffer, conditions_size); + pm_buffer_append_varint(buffer, conditions_size); for (uint32_t index = 0; index < conditions_size; index++) { pm_serialize_node(parser, (pm_node_t *) ((pm_when_node_t *)node)->conditions.nodes[index], buffer); } if (((pm_when_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_when_node_t *)node)->statements, buffer); } @@ -1162,11 +1221,11 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { case PM_WHILE_NODE: { pm_serialize_node(parser, (pm_node_t *)((pm_while_node_t *)node)->predicate, buffer); if (((pm_while_node_t *)node)->statements == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_while_node_t *)node)->statements, buffer); } - pm_buffer_append_u32(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + pm_buffer_append_varint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); break; } case PM_X_STRING_NODE: { @@ -1175,7 +1234,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } case PM_YIELD_NODE: { if (((pm_yield_node_t *)node)->arguments == NULL) { - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); } else { pm_serialize_node(parser, (pm_node_t *)((pm_yield_node_t *)node)->arguments, buffer); } @@ -1187,16 +1246,16 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { static void pm_serialize_comment(pm_parser_t *parser, pm_comment_t *comment, pm_buffer_t *buffer) { // serialize type - pm_buffer_append_u8(buffer, (uint8_t) comment->type); + pm_buffer_append_byte(buffer, (uint8_t) comment->type); // serialize location - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(comment->start - parser->start)); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(comment->end - comment->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(comment->start - parser->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(comment->end - comment->start)); } static void pm_serialize_comment_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t *buffer) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(pm_list_size(list))); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(pm_list_size(list))); pm_comment_t *comment; for (comment = (pm_comment_t *) list->head; comment != NULL; comment = (pm_comment_t *) comment->node.next) { @@ -1207,17 +1266,17 @@ pm_serialize_comment_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t *buf static void pm_serialize_magic_comment(pm_parser_t *parser, pm_magic_comment_t *magic_comment, pm_buffer_t *buffer) { // serialize key location - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(magic_comment->key_start - parser->start)); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(magic_comment->key_length)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(magic_comment->key_start - parser->start)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(magic_comment->key_length)); // serialize value location - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(magic_comment->value_start - parser->start)); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(magic_comment->value_length)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(magic_comment->value_start - parser->start)); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(magic_comment->value_length)); } static void pm_serialize_magic_comment_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t *buffer) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(pm_list_size(list))); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(pm_list_size(list))); pm_magic_comment_t *magic_comment; for (magic_comment = (pm_magic_comment_t *) list->head; magic_comment != NULL; magic_comment = (pm_magic_comment_t *) magic_comment->node.next) { @@ -1229,17 +1288,17 @@ static void pm_serialize_diagnostic(pm_parser_t *parser, pm_diagnostic_t *diagnostic, pm_buffer_t *buffer) { // serialize message size_t message_length = strlen(diagnostic->message); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(message_length)); - pm_buffer_append_str(buffer, diagnostic->message, message_length); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(message_length)); + pm_buffer_append_string(buffer, diagnostic->message, message_length); // serialize location - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(diagnostic->start - parser->start)); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(diagnostic->end - diagnostic->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(diagnostic->start - parser->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(diagnostic->end - diagnostic->start)); } static void pm_serialize_diagnostic_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t *buffer) { - pm_buffer_append_u32(buffer, pm_sizet_to_u32(pm_list_size(list))); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(pm_list_size(list))); pm_diagnostic_t *diagnostic; for (diagnostic = (pm_diagnostic_t *) list->head; diagnostic != NULL; diagnostic = (pm_diagnostic_t *) diagnostic->node.next) { @@ -1250,15 +1309,14 @@ pm_serialize_diagnostic_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t * static void pm_serialize_encoding(pm_encoding_t *encoding, pm_buffer_t *buffer) { size_t encoding_length = strlen(encoding->name); - pm_buffer_append_u32(buffer, pm_sizet_to_u32(encoding_length)); - pm_buffer_append_str(buffer, encoding->name, encoding_length); + pm_buffer_append_varint(buffer, pm_sizet_to_u32(encoding_length)); + pm_buffer_append_string(buffer, encoding->name, encoding_length); } #line 200 "serialize.c.erb" void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_serialize_encoding(&parser->encoding, buffer); - pm_serialize_comment_list(parser, &parser->comment_list, buffer); pm_serialize_magic_comment_list(parser, &parser->magic_comment_list, buffer); pm_serialize_diagnostic_list(parser, &parser->error_list, buffer); pm_serialize_diagnostic_list(parser, &parser->warning_list, buffer); @@ -1269,7 +1327,7 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) pm_buffer_append_zeroes(buffer, 4); // Next, encode the length of the constant pool. - pm_buffer_append_u32(buffer, parser->constant_pool.size); + pm_buffer_append_varint(buffer, parser->constant_pool.size); // Now we're going to serialize the content of the node. pm_serialize_node(parser, node, buffer); @@ -1292,12 +1350,12 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) pm_constant_t *constant = &parser->constant_pool.constants[bucket->id - 1]; size_t buffer_offset = offset + ((((size_t)bucket->id) - 1) * 8); - if (bucket->owned) { - // Since this is an owned constant, we are going to write its - // contents into the buffer after the constant pool. So - // effectively in place of the source offset, we have a buffer - // offset. We will add a leading 1 to indicate that this is a - // buffer offset. + if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED || bucket->type == PM_CONSTANT_POOL_BUCKET_CONSTANT) { + // Since this is an owned or constant constant, we are going to + // write its contents into the buffer after the constant pool. + // So effectively in place of the source offset, we have a + // buffer offset. We will add a leading 1 to indicate that this + // is a buffer offset. uint32_t content_offset = pm_sizet_to_u32(buffer->length); uint32_t owned_mask = (uint32_t) (1 << 31); @@ -1324,10 +1382,10 @@ static void serialize_token(void *data, pm_parser_t *parser, pm_token_t *token) { pm_buffer_t *buffer = (pm_buffer_t *) data; - pm_buffer_append_u32(buffer, token->type); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(token->start - parser->start)); - pm_buffer_append_u32(buffer, pm_ptrdifft_to_u32(token->end - token->start)); - pm_buffer_append_u32(buffer, parser->lex_state); + pm_buffer_append_varint(buffer, token->type); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(token->start - parser->start)); + pm_buffer_append_varint(buffer, pm_ptrdifft_to_u32(token->end - token->start)); + pm_buffer_append_varint(buffer, parser->lex_state); } PRISM_EXPORTED_FUNCTION void @@ -1344,7 +1402,7 @@ pm_lex_serialize(const uint8_t *source, size_t size, const char *filepath, pm_bu pm_node_t *node = pm_parse(&parser); // Append 0 to mark end of tokens - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); pm_serialize_encoding(&parser.encoding, buffer); pm_serialize_comment_list(&parser, &parser.comment_list, buffer); @@ -1372,7 +1430,7 @@ pm_parse_lex_serialize(const uint8_t *source, size_t size, pm_buffer_t *buffer, parser.lex_callback = &lex_callback; pm_node_t *node = pm_parse(&parser); - pm_buffer_append_u8(buffer, 0); + pm_buffer_append_byte(buffer, 0); pm_serialize(&parser, node, buffer); pm_node_destroy(&parser, node); diff --git a/src/main/c/yarp/src/util/pm_buffer.c b/src/main/c/yarp/src/util/pm_buffer.c index 55f6b0f7f390..db2415a8077d 100644 --- a/src/main/c/yarp/src/util/pm_buffer.c +++ b/src/main/c/yarp/src/util/pm_buffer.c @@ -40,9 +40,13 @@ pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { size_t next_length = buffer->length + length; if (next_length > buffer->capacity) { - do { + if (buffer->capacity == 0) { + buffer->capacity = 1; + } + + while (next_length > buffer->capacity) { buffer->capacity *= 2; - } while (next_length > buffer->capacity); + } buffer->value = realloc(buffer->value, buffer->capacity); } @@ -53,20 +57,43 @@ pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { // Append a generic pointer to memory to the buffer. static inline void pm_buffer_append(pm_buffer_t *buffer, const void *source, size_t length) { + size_t cursor = buffer->length; pm_buffer_append_length(buffer, length); - memcpy(buffer->value + (buffer->length - length), source, length); + memcpy(buffer->value + cursor, source, length); } // Append the given amount of space as zeroes to the buffer. void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length) { + size_t cursor = buffer->length; pm_buffer_append_length(buffer, length); - memset(buffer->value + (buffer->length - length), 0, 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_str(pm_buffer_t *buffer, const char *value, size_t length) { +pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length) { pm_buffer_append(buffer, value, length); } @@ -78,27 +105,35 @@ pm_buffer_append_bytes(pm_buffer_t *buffer, const uint8_t *value, size_t length) // Append a single byte to the buffer. void -pm_buffer_append_u8(pm_buffer_t *buffer, uint8_t value) { +pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value) { const void *source = &value; pm_buffer_append(buffer, source, sizeof(uint8_t)); } -// Append a 32-bit unsigned integer to the buffer. +// Append a 32-bit unsigned integer to the buffer as a variable-length integer. void -pm_buffer_append_u32(pm_buffer_t *buffer, uint32_t value) { +pm_buffer_append_varint(pm_buffer_t *buffer, uint32_t value) { if (value < 128) { - pm_buffer_append_u8(buffer, (uint8_t) value); + pm_buffer_append_byte(buffer, (uint8_t) value); } else { uint32_t n = value; while (n >= 128) { - pm_buffer_append_u8(buffer, (uint8_t) (n | 128)); + pm_buffer_append_byte(buffer, (uint8_t) (n | 128)); n >>= 7; } - pm_buffer_append_u8(buffer, (uint8_t) n); + pm_buffer_append_byte(buffer, (uint8_t) n); + } +} + +// Concatenate one buffer onto another. +void +pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source) { + if (source->length > 0) { + pm_buffer_append(destination, source->value, source->length); } } -// Free the memory associated with the buffer. +// Free the internal memory associated with the buffer. void pm_buffer_free(pm_buffer_t *buffer) { free(buffer->value); diff --git a/src/main/c/yarp/src/util/pm_constant_pool.c b/src/main/c/yarp/src/util/pm_constant_pool.c index d2c4f1e16c17..7d76f8370e0c 100644 --- a/src/main/c/yarp/src/util/pm_constant_pool.c +++ b/src/main/c/yarp/src/util/pm_constant_pool.c @@ -154,9 +154,16 @@ pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity) { return true; } +// Return a pointer to the constant indicated by the given constant id. +pm_constant_t * +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]; +} + // Insert a constant into a constant pool and return its index in the pool. static inline pm_constant_id_t -pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t length, bool owned) { +pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t length, pm_constant_pool_bucket_type_t type) { if (pool->size >= (pool->capacity / 4 * 3)) { if (!pm_constant_pool_resize(pool)) return 0; } @@ -178,19 +185,19 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l // Since we have found a match, we need to check if this is // attempting to insert a shared or an owned constant. We want to // prefer shared constants since they don't require allocations. - if (owned) { + if (type == PM_CONSTANT_POOL_BUCKET_OWNED) { // If we're attempting to insert an owned constant and we have // an existing constant, then either way we don't want the given // memory. Either it's duplicated with the existing constant or // it's not necessary because we have a shared version. free((void *) start); - } else if (bucket->owned) { + } else if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { // If we're attempting to insert a shared constant and the // existing constant is owned, then we can free the owned // constant and replace it with the shared constant. free((void *) constant->start); constant->start = start; - bucket->owned = false; + bucket->type = (unsigned int) (PM_CONSTANT_POOL_BUCKET_DEFAULT & 0x3); } return bucket->id; @@ -202,15 +209,15 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l // IDs are allocated starting at 1, since the value 0 denotes a non-existant // constant. uint32_t id = ++pool->size; - assert(pool->size < ((uint32_t) (1 << 31))); + assert(pool->size < ((uint32_t) (1 << 30))); *bucket = (pm_constant_pool_bucket_t) { - .id = (unsigned int) (id & 0x7FFFFFFF), - .owned = owned, + .id = (unsigned int) (id & 0x3fffffff), + .type = (unsigned int) (type & 0x3), .hash = hash }; - pool->constants[id - 1] = (pm_constant_t) { + pool->constants[id - 1] = (pm_constant_t) { .start = start, .length = length, }; @@ -222,7 +229,7 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l // if any potential calls to resize fail. pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { - return pm_constant_pool_insert(pool, start, length, false); + return pm_constant_pool_insert(pool, start, length, PM_CONSTANT_POOL_BUCKET_DEFAULT); } // Insert a constant into a constant pool from memory that is now owned by the @@ -230,7 +237,14 @@ pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, s // resize fail. pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { - return pm_constant_pool_insert(pool, start, length, true); + return pm_constant_pool_insert(pool, start, length, PM_CONSTANT_POOL_BUCKET_OWNED); +} + +// Insert a constant into a constant pool from memory that is constant. Returns +// the id of the constant, or 0 if any potential calls to resize fail. +pm_constant_id_t +pm_constant_pool_insert_constant(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { + return pm_constant_pool_insert(pool, start, length, PM_CONSTANT_POOL_BUCKET_CONSTANT); } // Free the memory associated with a constant pool. @@ -242,7 +256,7 @@ pm_constant_pool_free(pm_constant_pool_t *pool) { pm_constant_pool_bucket_t *bucket = &pool->buckets[index]; // If an id is set on this constant, then we know we have content here. - if (bucket->id != 0 && bucket->owned) { + if (bucket->id != 0 && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { pm_constant_t *constant = &pool->constants[bucket->id - 1]; free((void *) constant->start); } diff --git a/src/main/c/yarp/src/util/pm_newline_list.c b/src/main/c/yarp/src/util/pm_newline_list.c index 779a0a8d5c43..20a1a221cbe3 100644 --- a/src/main/c/yarp/src/util/pm_newline_list.c +++ b/src/main/c/yarp/src/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/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java b/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java index 06c737872973..921539864e8f 100644 --- a/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java +++ b/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java @@ -278,7 +278,7 @@ Object serialize(Object code, } } - @CoreMethod(names = "yarp_parse", onSingleton = true, required = 1) + @CoreMethod(names = { "yarp_parse", "prism_parse" }, onSingleton = true, required = 1) public abstract static class YARPParseNode extends CoreMethodArrayArgumentsNode { @TruffleBoundary @Specialization(guards = "strings.isRubyString(code)", limit = "1") diff --git a/src/main/java/org/truffleruby/parser/YARPTranslator.java b/src/main/java/org/truffleruby/parser/YARPTranslator.java index 14451aa1dd29..cff898d47ec8 100644 --- a/src/main/java/org/truffleruby/parser/YARPTranslator.java +++ b/src/main/java/org/truffleruby/parser/YARPTranslator.java @@ -1088,6 +1088,21 @@ public RubyNode visitInNode(Nodes.InNode node) { return defaultVisit(node); } + @Override + public RubyNode visitIndexAndWriteNode(Nodes.IndexAndWriteNode node) { + return super.visitIndexAndWriteNode(node); + } + + @Override + public RubyNode visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) { + return super.visitIndexOperatorWriteNode(node); + } + + @Override + public RubyNode visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) { + return super.visitIndexOrWriteNode(node); + } + @Override public RubyNode visitInstanceVariableAndWriteNode(Nodes.InstanceVariableAndWriteNode node) { return defaultVisit(node); @@ -2079,4 +2094,5 @@ private RubyNode[] translate(Nodes.Node[] nodes) { return rubyNodes; } + } diff --git a/src/yarp/java/org/prism/AbstractNodeVisitor.java b/src/yarp/java/org/prism/AbstractNodeVisitor.java index 96464da1d40a..17877b455c63 100644 --- a/src/yarp/java/org/prism/AbstractNodeVisitor.java +++ b/src/yarp/java/org/prism/AbstractNodeVisitor.java @@ -284,6 +284,18 @@ public T visitInNode(Nodes.InNode node) { return defaultVisit(node); } + public T visitIndexAndWriteNode(Nodes.IndexAndWriteNode node) { + return defaultVisit(node); + } + + public T visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) { + return defaultVisit(node); + } + + public T visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) { + return defaultVisit(node); + } + public T visitInstanceVariableAndWriteNode(Nodes.InstanceVariableAndWriteNode node) { return defaultVisit(node); } @@ -472,10 +484,6 @@ public T visitRegularExpressionNode(Nodes.RegularExpressionNode node) { return defaultVisit(node); } - public T visitRequiredDestructuredParameterNode(Nodes.RequiredDestructuredParameterNode node) { - return defaultVisit(node); - } - public T visitRequiredParameterNode(Nodes.RequiredParameterNode node) { return defaultVisit(node); } diff --git a/src/yarp/java/org/prism/Loader.java b/src/yarp/java/org/prism/Loader.java index 8d57ff16a70f..8d4ed2cbedbe 100644 --- a/src/yarp/java/org/prism/Loader.java +++ b/src/yarp/java/org/prism/Loader.java @@ -98,8 +98,8 @@ private ParseResult load() { expect((byte) 'M', "incorrect prism header"); expect((byte) 0, "prism version does not match"); - expect((byte) 14, "prism version does not match"); - expect((byte) 0, "prism version does not match"); + expect((byte) 15, "prism version does not match"); + expect((byte) 1, "prism version does not match"); expect((byte) 1, "Loader.java requires no location fields in the serialized output"); @@ -110,7 +110,6 @@ private ParseResult load() { this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); this.encodingCharset = getEncodingCharset(this.encodingName); - ParseResult.Comment[] comments = loadComments(); ParseResult.MagicComment[] magicComments = loadMagicComments(); ParseResult.Error[] errors = loadSyntaxErrors(); ParseResult.Warning[] warnings = loadWarnings(); @@ -130,7 +129,7 @@ private ParseResult load() { MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source, newlineMarked); node.accept(visitor); - return new ParseResult(node, comments, magicComments, errors, warnings); + return new ParseResult(node, magicComments, errors, warnings); } private byte[] loadEmbeddedString() { @@ -155,21 +154,6 @@ private byte[] loadString() { } } - private ParseResult.Comment[] loadComments() { - int count = loadVarInt(); - ParseResult.Comment[] comments = new ParseResult.Comment[count]; - - for (int i = 0; i < count; i++) { - ParseResult.CommentType type = ParseResult.CommentType.VALUES[buffer.get()]; - Nodes.Location location = loadLocation(); - - ParseResult.Comment comment = new ParseResult.Comment(type, location); - comments[i] = comment; - } - - return comments; - } - private ParseResult.MagicComment[] loadMagicComments() { int count = loadVarInt(); ParseResult.MagicComment[] magicComments = new ParseResult.MagicComment[count]; @@ -316,7 +300,7 @@ private Nodes.Node loadNode() { case 4: return new Nodes.AndNode(loadNode(), loadNode(), startOffset, length); case 5: - return new Nodes.ArgumentsNode(loadNodes(), startOffset, length); + return new Nodes.ArgumentsNode(loadNodes(), loadFlags(), startOffset, length); case 6: return new Nodes.ArrayNode(loadNodes(), startOffset, length); case 7: @@ -342,13 +326,13 @@ private Nodes.Node loadNode() { case 17: return new Nodes.BreakNode((Nodes.ArgumentsNode) loadOptionalNode(), startOffset, length); case 18: - return new Nodes.CallAndWriteNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadFlags(), loadConstant(), loadConstant(), loadNode(), startOffset, length); + return new Nodes.CallAndWriteNode(loadOptionalNode(), loadFlags(), loadConstant(), loadConstant(), loadNode(), startOffset, length); case 19: return new Nodes.CallNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode(), loadFlags(), loadConstant(), startOffset, length); case 20: - return new Nodes.CallOperatorWriteNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadFlags(), loadConstant(), loadConstant(), loadConstant(), loadNode(), startOffset, length); + return new Nodes.CallOperatorWriteNode(loadOptionalNode(), loadFlags(), loadConstant(), loadConstant(), loadConstant(), loadNode(), startOffset, length); case 21: - return new Nodes.CallOrWriteNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadFlags(), loadConstant(), loadConstant(), loadNode(), startOffset, length); + return new Nodes.CallOrWriteNode(loadOptionalNode(), loadFlags(), loadConstant(), loadConstant(), loadNode(), startOffset, length); case 22: return new Nodes.CapturePatternNode(loadNode(), loadNode(), startOffset, length); case 23: @@ -444,150 +428,154 @@ private Nodes.Node loadNode() { case 68: return new Nodes.InNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), startOffset, length); case 69: - return new Nodes.InstanceVariableAndWriteNode(loadConstant(), loadNode(), startOffset, length); + return new Nodes.IndexAndWriteNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode(), loadFlags(), loadNode(), startOffset, length); case 70: - return new Nodes.InstanceVariableOperatorWriteNode(loadConstant(), loadNode(), loadConstant(), startOffset, length); + return new Nodes.IndexOperatorWriteNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode(), loadFlags(), loadConstant(), loadNode(), startOffset, length); case 71: - return new Nodes.InstanceVariableOrWriteNode(loadConstant(), loadNode(), startOffset, length); + return new Nodes.IndexOrWriteNode(loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode(), loadFlags(), loadNode(), startOffset, length); case 72: - return new Nodes.InstanceVariableReadNode(loadConstant(), startOffset, length); + return new Nodes.InstanceVariableAndWriteNode(loadConstant(), loadNode(), startOffset, length); case 73: - return new Nodes.InstanceVariableTargetNode(loadConstant(), startOffset, length); + return new Nodes.InstanceVariableOperatorWriteNode(loadConstant(), loadNode(), loadConstant(), startOffset, length); case 74: - return new Nodes.InstanceVariableWriteNode(loadConstant(), loadNode(), startOffset, length); + return new Nodes.InstanceVariableOrWriteNode(loadConstant(), loadNode(), startOffset, length); case 75: - return new Nodes.IntegerNode(loadFlags(), startOffset, length); + return new Nodes.InstanceVariableReadNode(loadConstant(), startOffset, length); case 76: - return new Nodes.InterpolatedMatchLastLineNode(loadNodes(), loadFlags(), startOffset, length); + return new Nodes.InstanceVariableTargetNode(loadConstant(), startOffset, length); case 77: - return new Nodes.InterpolatedRegularExpressionNode(loadNodes(), loadFlags(), startOffset, length); + return new Nodes.InstanceVariableWriteNode(loadConstant(), loadNode(), startOffset, length); case 78: - return new Nodes.InterpolatedStringNode(loadNodes(), startOffset, length); + return new Nodes.IntegerNode(loadFlags(), startOffset, length); case 79: - return new Nodes.InterpolatedSymbolNode(loadNodes(), startOffset, length); + return new Nodes.InterpolatedMatchLastLineNode(loadNodes(), loadFlags(), startOffset, length); case 80: - return new Nodes.InterpolatedXStringNode(loadNodes(), startOffset, length); + return new Nodes.InterpolatedRegularExpressionNode(loadNodes(), loadFlags(), startOffset, length); case 81: - return new Nodes.KeywordHashNode(loadNodes(), startOffset, length); + return new Nodes.InterpolatedStringNode(loadNodes(), startOffset, length); case 82: - return new Nodes.KeywordParameterNode(loadConstant(), loadOptionalNode(), startOffset, length); + return new Nodes.InterpolatedSymbolNode(loadNodes(), startOffset, length); case 83: - return new Nodes.KeywordRestParameterNode(loadOptionalConstant(), startOffset, length); + return new Nodes.InterpolatedXStringNode(loadNodes(), startOffset, length); case 84: - return new Nodes.LambdaNode(loadConstants(), (Nodes.BlockParametersNode) loadOptionalNode(), loadOptionalNode(), startOffset, length); + return new Nodes.KeywordHashNode(loadNodes(), startOffset, length); case 85: - return new Nodes.LocalVariableAndWriteNode(loadNode(), loadConstant(), loadVarInt(), startOffset, length); + return new Nodes.KeywordParameterNode(loadConstant(), loadOptionalNode(), startOffset, length); case 86: - return new Nodes.LocalVariableOperatorWriteNode(loadNode(), loadConstant(), loadConstant(), loadVarInt(), startOffset, length); + return new Nodes.KeywordRestParameterNode(loadOptionalConstant(), startOffset, length); case 87: - return new Nodes.LocalVariableOrWriteNode(loadNode(), loadConstant(), loadVarInt(), startOffset, length); + return new Nodes.LambdaNode(loadConstants(), (Nodes.BlockParametersNode) loadOptionalNode(), loadOptionalNode(), startOffset, length); case 88: - return new Nodes.LocalVariableReadNode(loadConstant(), loadVarInt(), startOffset, length); + return new Nodes.LocalVariableAndWriteNode(loadNode(), loadConstant(), loadVarInt(), startOffset, length); case 89: - return new Nodes.LocalVariableTargetNode(loadConstant(), loadVarInt(), startOffset, length); + return new Nodes.LocalVariableOperatorWriteNode(loadNode(), loadConstant(), loadConstant(), loadVarInt(), startOffset, length); case 90: - return new Nodes.LocalVariableWriteNode(loadConstant(), loadVarInt(), loadNode(), startOffset, length); + return new Nodes.LocalVariableOrWriteNode(loadNode(), loadConstant(), loadVarInt(), startOffset, length); case 91: - return new Nodes.MatchLastLineNode(loadString(), loadFlags(), startOffset, length); + return new Nodes.LocalVariableReadNode(loadConstant(), loadVarInt(), startOffset, length); case 92: - return new Nodes.MatchPredicateNode(loadNode(), loadNode(), startOffset, length); + return new Nodes.LocalVariableTargetNode(loadConstant(), loadVarInt(), startOffset, length); case 93: - return new Nodes.MatchRequiredNode(loadNode(), loadNode(), startOffset, length); + return new Nodes.LocalVariableWriteNode(loadConstant(), loadVarInt(), loadNode(), startOffset, length); case 94: - return new Nodes.MatchWriteNode((Nodes.CallNode) loadNode(), loadConstants(), startOffset, length); + return new Nodes.MatchLastLineNode(loadString(), loadFlags(), startOffset, length); case 95: - return new Nodes.MissingNode(startOffset, length); + return new Nodes.MatchPredicateNode(loadNode(), loadNode(), startOffset, length); case 96: - return new Nodes.ModuleNode(loadConstants(), loadNode(), loadOptionalNode(), loadConstant(), startOffset, length); + return new Nodes.MatchRequiredNode(loadNode(), loadNode(), startOffset, length); case 97: - return new Nodes.MultiTargetNode(loadNodes(), startOffset, length); + return new Nodes.MatchWriteNode((Nodes.CallNode) loadNode(), loadConstants(), startOffset, length); case 98: - return new Nodes.MultiWriteNode(loadNodes(), loadNode(), startOffset, length); + return new Nodes.MissingNode(startOffset, length); case 99: - return new Nodes.NextNode((Nodes.ArgumentsNode) loadOptionalNode(), startOffset, length); + return new Nodes.ModuleNode(loadConstants(), loadNode(), loadOptionalNode(), loadConstant(), startOffset, length); case 100: - return new Nodes.NilNode(startOffset, length); + return new Nodes.MultiTargetNode(loadNodes(), loadOptionalNode(), loadNodes(), startOffset, length); case 101: - return new Nodes.NoKeywordsParameterNode(startOffset, length); + return new Nodes.MultiWriteNode(loadNodes(), loadOptionalNode(), loadNodes(), loadNode(), startOffset, length); case 102: - return new Nodes.NumberedReferenceReadNode(loadVarInt(), startOffset, length); + return new Nodes.NextNode((Nodes.ArgumentsNode) loadOptionalNode(), startOffset, length); case 103: - return new Nodes.OptionalParameterNode(loadConstant(), loadNode(), startOffset, length); + return new Nodes.NilNode(startOffset, length); case 104: - return new Nodes.OrNode(loadNode(), loadNode(), startOffset, length); + return new Nodes.NoKeywordsParameterNode(startOffset, length); case 105: - return new Nodes.ParametersNode(loadNodes(), loadNodes(), (Nodes.RestParameterNode) loadOptionalNode(), loadNodes(), loadNodes(), loadOptionalNode(), (Nodes.BlockParameterNode) loadOptionalNode(), startOffset, length); + return new Nodes.NumberedReferenceReadNode(loadVarInt(), startOffset, length); case 106: - return new Nodes.ParenthesesNode(loadOptionalNode(), startOffset, length); + return new Nodes.OptionalParameterNode(loadConstant(), loadNode(), startOffset, length); case 107: - return new Nodes.PinnedExpressionNode(loadNode(), startOffset, length); + return new Nodes.OrNode(loadNode(), loadNode(), startOffset, length); case 108: - return new Nodes.PinnedVariableNode(loadNode(), startOffset, length); + return new Nodes.ParametersNode(loadNodes(), loadNodes(), (Nodes.RestParameterNode) loadOptionalNode(), loadNodes(), loadNodes(), loadOptionalNode(), (Nodes.BlockParameterNode) loadOptionalNode(), startOffset, length); case 109: - return new Nodes.PostExecutionNode((Nodes.StatementsNode) loadOptionalNode(), startOffset, length); + return new Nodes.ParenthesesNode(loadOptionalNode(), startOffset, length); case 110: - return new Nodes.PreExecutionNode((Nodes.StatementsNode) loadOptionalNode(), startOffset, length); + return new Nodes.PinnedExpressionNode(loadNode(), startOffset, length); case 111: - return new Nodes.ProgramNode(loadConstants(), (Nodes.StatementsNode) loadNode(), startOffset, length); + return new Nodes.PinnedVariableNode(loadNode(), startOffset, length); case 112: - return new Nodes.RangeNode(loadOptionalNode(), loadOptionalNode(), loadFlags(), startOffset, length); + return new Nodes.PostExecutionNode((Nodes.StatementsNode) loadOptionalNode(), startOffset, length); case 113: - return new Nodes.RationalNode(loadNode(), startOffset, length); + return new Nodes.PreExecutionNode((Nodes.StatementsNode) loadOptionalNode(), startOffset, length); case 114: - return new Nodes.RedoNode(startOffset, length); + return new Nodes.ProgramNode(loadConstants(), (Nodes.StatementsNode) loadNode(), startOffset, length); case 115: - return new Nodes.RegularExpressionNode(loadString(), loadFlags(), startOffset, length); + return new Nodes.RangeNode(loadOptionalNode(), loadOptionalNode(), loadFlags(), startOffset, length); case 116: - return new Nodes.RequiredDestructuredParameterNode(loadNodes(), startOffset, length); + return new Nodes.RationalNode(loadNode(), startOffset, length); case 117: - return new Nodes.RequiredParameterNode(loadConstant(), startOffset, length); + return new Nodes.RedoNode(startOffset, length); case 118: - return new Nodes.RescueModifierNode(loadNode(), loadNode(), startOffset, length); + return new Nodes.RegularExpressionNode(loadString(), loadFlags(), startOffset, length); case 119: - return new Nodes.RescueNode(loadNodes(), loadOptionalNode(), (Nodes.StatementsNode) loadOptionalNode(), (Nodes.RescueNode) loadOptionalNode(), startOffset, length); + return new Nodes.RequiredParameterNode(loadConstant(), startOffset, length); case 120: - return new Nodes.RestParameterNode(loadOptionalConstant(), startOffset, length); + return new Nodes.RescueModifierNode(loadNode(), loadNode(), startOffset, length); case 121: - return new Nodes.RetryNode(startOffset, length); + return new Nodes.RescueNode(loadNodes(), loadOptionalNode(), (Nodes.StatementsNode) loadOptionalNode(), (Nodes.RescueNode) loadOptionalNode(), startOffset, length); case 122: - return new Nodes.ReturnNode((Nodes.ArgumentsNode) loadOptionalNode(), startOffset, length); + return new Nodes.RestParameterNode(loadOptionalConstant(), startOffset, length); case 123: - return new Nodes.SelfNode(startOffset, length); + return new Nodes.RetryNode(startOffset, length); case 124: - return new Nodes.SingletonClassNode(loadConstants(), loadNode(), loadOptionalNode(), startOffset, length); + return new Nodes.ReturnNode((Nodes.ArgumentsNode) loadOptionalNode(), startOffset, length); case 125: - return new Nodes.SourceEncodingNode(startOffset, length); + return new Nodes.SelfNode(startOffset, length); case 126: - return new Nodes.SourceFileNode(loadString(), startOffset, length); + return new Nodes.SingletonClassNode(loadConstants(), loadNode(), loadOptionalNode(), startOffset, length); case 127: - return new Nodes.SourceLineNode(startOffset, length); + return new Nodes.SourceEncodingNode(startOffset, length); case 128: - return new Nodes.SplatNode(loadOptionalNode(), startOffset, length); + return new Nodes.SourceFileNode(loadString(), startOffset, length); case 129: - return new Nodes.StatementsNode(loadNodes(), startOffset, length); + return new Nodes.SourceLineNode(startOffset, length); case 130: - return new Nodes.StringConcatNode(loadNode(), loadNode(), startOffset, length); + return new Nodes.SplatNode(loadOptionalNode(), startOffset, length); case 131: - return new Nodes.StringNode(loadFlags(), loadString(), startOffset, length); + return new Nodes.StatementsNode(loadNodes(), startOffset, length); case 132: - return new Nodes.SuperNode((Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode(), startOffset, length); + return new Nodes.StringConcatNode(loadNode(), loadNode(), startOffset, length); case 133: - return new Nodes.SymbolNode(loadString(), startOffset, length); + return new Nodes.StringNode(loadFlags(), loadString(), startOffset, length); case 134: - return new Nodes.TrueNode(startOffset, length); + return new Nodes.SuperNode((Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode(), startOffset, length); case 135: - return new Nodes.UndefNode(loadNodes(), startOffset, length); + return new Nodes.SymbolNode(loadString(), startOffset, length); case 136: - return new Nodes.UnlessNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), (Nodes.ElseNode) loadOptionalNode(), startOffset, length); + return new Nodes.TrueNode(startOffset, length); case 137: - return new Nodes.UntilNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), loadFlags(), startOffset, length); + return new Nodes.UndefNode(loadNodes(), startOffset, length); case 138: - return new Nodes.WhenNode(loadNodes(), (Nodes.StatementsNode) loadOptionalNode(), startOffset, length); + return new Nodes.UnlessNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), (Nodes.ElseNode) loadOptionalNode(), startOffset, length); case 139: - return new Nodes.WhileNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), loadFlags(), startOffset, length); + return new Nodes.UntilNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), loadFlags(), startOffset, length); case 140: - return new Nodes.XStringNode(loadString(), startOffset, length); + return new Nodes.WhenNode(loadNodes(), (Nodes.StatementsNode) loadOptionalNode(), startOffset, length); case 141: + return new Nodes.WhileNode(loadNode(), (Nodes.StatementsNode) loadOptionalNode(), loadFlags(), startOffset, length); + case 142: + return new Nodes.XStringNode(loadString(), startOffset, length); + case 143: return new Nodes.YieldNode((Nodes.ArgumentsNode) loadOptionalNode(), startOffset, length); default: throw new Error("Unknown node type: " + type); diff --git a/src/yarp/java/org/prism/Nodes.java b/src/yarp/java/org/prism/Nodes.java index cc2dbb5dc5cc..4aa26aab2f40 100644 --- a/src/yarp/java/org/prism/Nodes.java +++ b/src/yarp/java/org/prism/Nodes.java @@ -129,6 +129,46 @@ public String toString() { protected abstract String toString(String indent); } + public static final class ArgumentsNodeFlags implements Comparable { + + // if arguments contain keyword splat + public static final short KEYWORD_SPLAT = 1 << 0; + + public static boolean isKeywordSplat(short flags) { + return (flags & KEYWORD_SPLAT) != 0; + } + + private final short flags; + + public ArgumentsNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ArgumentsNodeFlags)) { + return false; + } + + return flags == ((ArgumentsNodeFlags) other).flags; + } + + @Override + public int compareTo(ArgumentsNodeFlags other) { + return flags - other.flags; + } + + public boolean isKeywordSplat() { + return (flags & KEYWORD_SPLAT) != 0; + } + + } + public static final class CallNodeFlags implements Comparable { // &. operator @@ -680,12 +720,18 @@ protected String toString(String indent) { // ^^^^^^^^^^^^^ public static final class ArgumentsNode extends Node { public final Node[] arguments; + public final short flags; - public ArgumentsNode(Node[] arguments, int startOffset, int length) { + public ArgumentsNode(Node[] arguments, short flags, int startOffset, int length) { super(startOffset, length); this.arguments = arguments; + this.flags = flags; } - + + public boolean isKeywordSplat() { + return ArgumentsNodeFlags.isKeywordSplat(this.flags); + } + public void visitChildNodes(AbstractNodeVisitor visitor) { for (Nodes.Node child : this.arguments) { child.accept(visitor); @@ -716,6 +762,10 @@ protected String toString(String indent) { for (Node child : this.arguments) { builder.append(nextNextIndent).append(child.toString(nextNextIndent)); } + builder.append(nextIndent); + builder.append("flags: "); + builder.append(this.flags); + builder.append('\n'); return builder.toString(); } } @@ -1366,17 +1416,14 @@ protected String toString(String indent) { public static final class CallAndWriteNode extends Node { /** optional (can be null) */ public final Node receiver; - /** optional (can be null) */ - public final ArgumentsNode arguments; public final short flags; public final String read_name; public final String write_name; public final Node value; - public CallAndWriteNode(Node receiver, ArgumentsNode arguments, short flags, String read_name, String write_name, Node value, int startOffset, int length) { + public CallAndWriteNode(Node receiver, short flags, String read_name, String write_name, Node value, int startOffset, int length) { super(startOffset, length); this.receiver = receiver; - this.arguments = arguments; this.flags = flags; this.read_name = read_name; this.write_name = write_name; @@ -1395,14 +1442,11 @@ public void visitChildNodes(AbstractNodeVisitor visitor) { if (this.receiver != null) { this.receiver.accept(visitor); } - if (this.arguments != null) { - this.arguments.accept(visitor); - } this.value.accept(visitor); } public Node[] childNodes() { - return new Node[] { this.receiver, this.arguments, this.value }; + return new Node[] { this.receiver, this.value }; } public T accept(AbstractNodeVisitor visitor) { @@ -1422,9 +1466,6 @@ protected String toString(String indent) { builder.append("receiver: "); builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); builder.append(nextIndent); - builder.append("arguments: "); - builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); - builder.append(nextIndent); builder.append("flags: "); builder.append(this.flags); builder.append('\n'); @@ -1546,18 +1587,15 @@ protected String toString(String indent) { public static final class CallOperatorWriteNode extends Node { /** optional (can be null) */ public final Node receiver; - /** optional (can be null) */ - public final ArgumentsNode arguments; public final short flags; public final String read_name; public final String write_name; public final String operator; public final Node value; - public CallOperatorWriteNode(Node receiver, ArgumentsNode arguments, short flags, String read_name, String write_name, String operator, Node value, int startOffset, int length) { + public CallOperatorWriteNode(Node receiver, short flags, String read_name, String write_name, String operator, Node value, int startOffset, int length) { super(startOffset, length); this.receiver = receiver; - this.arguments = arguments; this.flags = flags; this.read_name = read_name; this.write_name = write_name; @@ -1577,14 +1615,11 @@ public void visitChildNodes(AbstractNodeVisitor visitor) { if (this.receiver != null) { this.receiver.accept(visitor); } - if (this.arguments != null) { - this.arguments.accept(visitor); - } this.value.accept(visitor); } public Node[] childNodes() { - return new Node[] { this.receiver, this.arguments, this.value }; + return new Node[] { this.receiver, this.value }; } public T accept(AbstractNodeVisitor visitor) { @@ -1604,9 +1639,6 @@ protected String toString(String indent) { builder.append("receiver: "); builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); builder.append(nextIndent); - builder.append("arguments: "); - builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); - builder.append(nextIndent); builder.append("flags: "); builder.append(this.flags); builder.append('\n'); @@ -1636,17 +1668,14 @@ protected String toString(String indent) { public static final class CallOrWriteNode extends Node { /** optional (can be null) */ public final Node receiver; - /** optional (can be null) */ - public final ArgumentsNode arguments; public final short flags; public final String read_name; public final String write_name; public final Node value; - public CallOrWriteNode(Node receiver, ArgumentsNode arguments, short flags, String read_name, String write_name, Node value, int startOffset, int length) { + public CallOrWriteNode(Node receiver, short flags, String read_name, String write_name, Node value, int startOffset, int length) { super(startOffset, length); this.receiver = receiver; - this.arguments = arguments; this.flags = flags; this.read_name = read_name; this.write_name = write_name; @@ -1665,14 +1694,11 @@ public void visitChildNodes(AbstractNodeVisitor visitor) { if (this.receiver != null) { this.receiver.accept(visitor); } - if (this.arguments != null) { - this.arguments.accept(visitor); - } this.value.accept(visitor); } public Node[] childNodes() { - return new Node[] { this.receiver, this.arguments, this.value }; + return new Node[] { this.receiver, this.value }; } public T accept(AbstractNodeVisitor visitor) { @@ -1692,9 +1718,6 @@ protected String toString(String indent) { builder.append("receiver: "); builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); builder.append(nextIndent); - builder.append("arguments: "); - builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); - builder.append(nextIndent); builder.append("flags: "); builder.append(this.flags); builder.append('\n'); @@ -3731,34 +3754,34 @@ protected String toString(String indent) { public static final class HashPatternNode extends Node { /** optional (can be null) */ public final Node constant; - public final Node[] assocs; + public final Node[] elements; /** optional (can be null) */ - public final Node kwrest; + public final Node rest; - public HashPatternNode(Node constant, Node[] assocs, Node kwrest, int startOffset, int length) { + public HashPatternNode(Node constant, Node[] elements, Node rest, int startOffset, int length) { super(startOffset, length); this.constant = constant; - this.assocs = assocs; - this.kwrest = kwrest; + this.elements = elements; + this.rest = rest; } public void visitChildNodes(AbstractNodeVisitor visitor) { if (this.constant != null) { this.constant.accept(visitor); } - for (Nodes.Node child : this.assocs) { + for (Nodes.Node child : this.elements) { child.accept(visitor); } - if (this.kwrest != null) { - this.kwrest.accept(visitor); + if (this.rest != null) { + this.rest.accept(visitor); } } public Node[] childNodes() { ArrayList childNodes = new ArrayList<>(); childNodes.add(this.constant); - childNodes.addAll(Arrays.asList(this.assocs)); - childNodes.add(this.kwrest); + childNodes.addAll(Arrays.asList(this.elements)); + childNodes.add(this.rest); return childNodes.toArray(EMPTY_ARRAY); } @@ -3780,14 +3803,14 @@ protected String toString(String indent) { builder.append("constant: "); builder.append(this.constant == null ? "null\n" : this.constant.toString(nextIndent)); builder.append(nextIndent); - builder.append("assocs: "); + builder.append("elements: "); builder.append('\n'); - for (Node child : this.assocs) { + for (Node child : this.elements) { builder.append(nextNextIndent).append(child.toString(nextNextIndent)); } builder.append(nextIndent); - builder.append("kwrest: "); - builder.append(this.kwrest == null ? "null\n" : this.kwrest.toString(nextIndent)); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); return builder.toString(); } } @@ -3991,6 +4014,255 @@ protected String toString(String indent) { } } + // Represents the use of the `&&=` operator on a call to the `[]` method. + // + // foo.bar[baz] &&= value + // ^^^^^^^^^^^^^^^^^^^^^^ + public static final class IndexAndWriteNode extends Node { + /** optional (can be null) */ + public final Node receiver; + /** optional (can be null) */ + public final ArgumentsNode arguments; + /** optional (can be null) */ + public final Node block; + public final short flags; + public final Node value; + + public IndexAndWriteNode(Node receiver, ArgumentsNode arguments, Node block, short flags, Node value, int startOffset, int length) { + super(startOffset, length); + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + this.flags = flags; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(this.flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(this.flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + builder.append(nextIndent); + builder.append("flags: "); + builder.append(this.flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + // Represents the use of an assignment operator on a call to `[]`. + // + // foo.bar[baz] += value + // ^^^^^^^^^^^^^^^^^^^^^ + public static final class IndexOperatorWriteNode extends Node { + /** optional (can be null) */ + public final Node receiver; + /** optional (can be null) */ + public final ArgumentsNode arguments; + /** optional (can be null) */ + public final Node block; + public final short flags; + public final String operator; + public final Node value; + + public IndexOperatorWriteNode(Node receiver, ArgumentsNode arguments, Node block, short flags, String operator, Node value, int startOffset, int length) { + super(startOffset, length); + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + this.flags = flags; + this.operator = operator; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(this.flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(this.flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + builder.append(nextIndent); + builder.append("flags: "); + builder.append(this.flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("operator: "); + builder.append('"').append(this.operator).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + // Represents the use of the `||=` operator on a call to `[]`. + // + // foo.bar[baz] ||= value + // ^^^^^^^^^^^^^^^^^^^^^^ + public static final class IndexOrWriteNode extends Node { + /** optional (can be null) */ + public final Node receiver; + /** optional (can be null) */ + public final ArgumentsNode arguments; + /** optional (can be null) */ + public final Node block; + public final short flags; + public final Node value; + + public IndexOrWriteNode(Node receiver, ArgumentsNode arguments, Node block, short flags, Node value, int startOffset, int length) { + super(startOffset, length); + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + this.flags = flags; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(this.flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(this.flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + builder.append(nextIndent); + builder.append("flags: "); + builder.append(this.flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + // Represents the use of the `&&=` operator for assignment to an instance variable. // // @target &&= value @@ -5496,24 +5768,39 @@ protected String toString(String indent) { // Represents a multi-target expression. // - // a, b, c = 1, 2, 3 - // ^^^^^^^ + // a, (b, c) = 1, 2, 3 + // ^^^^^^ public static final class MultiTargetNode extends Node { - public final Node[] targets; + public final Node[] lefts; + /** optional (can be null) */ + public final Node rest; + public final Node[] rights; - public MultiTargetNode(Node[] targets, int startOffset, int length) { + public MultiTargetNode(Node[] lefts, Node rest, Node[] rights, int startOffset, int length) { super(startOffset, length); - this.targets = targets; + this.lefts = lefts; + this.rest = rest; + this.rights = rights; } public void visitChildNodes(AbstractNodeVisitor visitor) { - for (Nodes.Node child : this.targets) { + for (Nodes.Node child : this.lefts) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + for (Nodes.Node child : this.rights) { child.accept(visitor); } } public Node[] childNodes() { - return this.targets; + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.lefts)); + childNodes.add(this.rest); + childNodes.addAll(Arrays.asList(this.rights)); + return childNodes.toArray(EMPTY_ARRAY); } public T accept(AbstractNodeVisitor visitor) { @@ -5531,9 +5818,18 @@ protected String toString(String indent) { String nextIndent = indent + " "; String nextNextIndent = nextIndent + " "; builder.append(nextIndent); - builder.append("targets: "); + builder.append("lefts: "); + builder.append('\n'); + for (Node child : this.lefts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("rights: "); builder.append('\n'); - for (Node child : this.targets) { + for (Node child : this.rights) { builder.append(nextNextIndent).append(child.toString(nextNextIndent)); } return builder.toString(); @@ -5545,17 +5841,28 @@ protected String toString(String indent) { // a, b, c = 1, 2, 3 // ^^^^^^^^^^^^^^^^^ public static final class MultiWriteNode extends Node { - public final Node[] targets; + public final Node[] lefts; + /** optional (can be null) */ + public final Node rest; + public final Node[] rights; public final Node value; - public MultiWriteNode(Node[] targets, Node value, int startOffset, int length) { + public MultiWriteNode(Node[] lefts, Node rest, Node[] rights, Node value, int startOffset, int length) { super(startOffset, length); - this.targets = targets; + this.lefts = lefts; + this.rest = rest; + this.rights = rights; this.value = value; } public void visitChildNodes(AbstractNodeVisitor visitor) { - for (Nodes.Node child : this.targets) { + for (Nodes.Node child : this.lefts) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + for (Nodes.Node child : this.rights) { child.accept(visitor); } this.value.accept(visitor); @@ -5563,7 +5870,9 @@ public void visitChildNodes(AbstractNodeVisitor visitor) { public Node[] childNodes() { ArrayList childNodes = new ArrayList<>(); - childNodes.addAll(Arrays.asList(this.targets)); + childNodes.addAll(Arrays.asList(this.lefts)); + childNodes.add(this.rest); + childNodes.addAll(Arrays.asList(this.rights)); childNodes.add(this.value); return childNodes.toArray(EMPTY_ARRAY); } @@ -5583,9 +5892,18 @@ protected String toString(String indent) { String nextIndent = indent + " "; String nextNextIndent = nextIndent + " "; builder.append(nextIndent); - builder.append("targets: "); + builder.append("lefts: "); + builder.append('\n'); + for (Node child : this.lefts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("rights: "); builder.append('\n'); - for (Node child : this.targets) { + for (Node child : this.rights) { builder.append(nextNextIndent).append(child.toString(nextNextIndent)); } builder.append(nextIndent); @@ -6434,53 +6752,6 @@ protected String toString(String indent) { } } - // Represents a destructured required parameter node. - // - // def foo((bar, baz)) - // ^^^^^^^^^^ - // end - public static final class RequiredDestructuredParameterNode extends Node { - public final Node[] parameters; - - public RequiredDestructuredParameterNode(Node[] parameters, int startOffset, int length) { - super(startOffset, length); - this.parameters = parameters; - } - - public void visitChildNodes(AbstractNodeVisitor visitor) { - for (Nodes.Node child : this.parameters) { - child.accept(visitor); - } - } - - public Node[] childNodes() { - return this.parameters; - } - - public T accept(AbstractNodeVisitor visitor) { - return visitor.visitRequiredDestructuredParameterNode(this); - } - - @Override - protected String toString(String indent) { - StringBuilder builder = new StringBuilder(); - builder.append(this.getClass().getSimpleName()); - if (hasNewLineFlag()) { - builder.append("[Li]"); - } - builder.append('\n'); - String nextIndent = indent + " "; - String nextNextIndent = nextIndent + " "; - builder.append(nextIndent); - builder.append("parameters: "); - builder.append('\n'); - for (Node child : this.parameters) { - builder.append(nextNextIndent).append(child.toString(nextNextIndent)); - } - return builder.toString(); - } - } - // Represents a required parameter to a method, block, or lambda definition. // // def a(b) diff --git a/src/yarp/java/org/prism/ParseResult.java b/src/yarp/java/org/prism/ParseResult.java index 615649bacfbc..281eed5f1f02 100644 --- a/src/yarp/java/org/prism/ParseResult.java +++ b/src/yarp/java/org/prism/ParseResult.java @@ -3,27 +3,6 @@ // @formatter:off public final class ParseResult { - public enum CommentType { - /** # comment */ - INLINE, - /** =begin/=end */ - EMBEDDED_DOCUMENT, - /** after __END__ */ - __END__; - - static final CommentType[] VALUES = values(); - } - - public static final class Comment { - public final CommentType type; - public final Nodes.Location location; - - public Comment(CommentType type, Nodes.Location location) { - this.type = type; - this.location = location; - } - } - public static final class MagicComment { public final Nodes.Location keyLocation; public final Nodes.Location valueLocation; @@ -55,14 +34,12 @@ public Warning(String message, Nodes.Location location) { } public final Nodes.Node value; - public final Comment[] comments; public final MagicComment[] magicComments; public final Error[] errors; public final Warning[] warnings; - public ParseResult(Nodes.Node value, Comment[] comments, MagicComment[] magicComments, Error[] errors, Warning[] warnings) { + public ParseResult(Nodes.Node value, MagicComment[] magicComments, Error[] errors, Warning[] warnings) { this.value = value; - this.comments = comments; this.magicComments = magicComments; this.errors = errors; this.warnings = warnings;