diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb index 301479b3c5..7b3e685a70 100644 --- a/prism/templates/ext/prism/api_node.c.erb +++ b/prism/templates/ext/prism/api_node.c.erb @@ -39,12 +39,21 @@ pm_string_new(const pm_string_t *string, rb_encoding *encoding) { static VALUE pm_integer_new(const pm_integer_t *integer) { - VALUE result = UINT2NUM(integer->head.value); - size_t shift = 0; - - for (const pm_integer_word_t *node = integer->head.next; node != NULL; node = node->next) { - VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); - result = rb_funcall(receiver, rb_intern("|"), 1, result); + VALUE result; + if (integer->head.next) { + size_t length = integer->length + 1; + VALUE str = rb_str_new(NULL, length * 8); + unsigned char *buf = (unsigned char *)RSTRING_PTR(str); + size_t offset = length * 8; + for (const pm_integer_word_t *node = &integer->head; node != NULL; node = node->next) { + for (int i = 0; i < 8; i++) { + int n = (node->value >> (4 * i)) & 0xf; + buf[--offset] = n < 10 ? n + '0' : n - 10 + 'a'; + } + } + result = rb_funcall(str, rb_intern("to_i"), 1, UINT2NUM(16)); + } else { + result = UINT2NUM(integer->head.value); } if (integer->negative) {