From c8703a17ceedae4a72f83c962a4d098731a85dda Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 18 May 2020 10:09:28 +0900 Subject: [PATCH] [Feature #16254] Allow `__builtin.func` style --- compile.c | 25 ++++++++++++++++++------- tool/mk_builtin_loader.rb | 23 ++++++++++++++++++++--- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/compile.c b/compile.c index 6316985b3d..13df6a0062 100644 --- a/compile.c +++ b/compile.c @@ -7039,18 +7039,30 @@ iseq_builtin_function_lookup(const rb_iseq_t *iseq, const char *name) } static const char * -iseq_builtin_function_name(ID mid) +iseq_builtin_function_name(const enum node_type type, const NODE *recv, ID mid) { const char *name = rb_id2name(mid); static const char prefix[] = "__builtin_"; const size_t prefix_len = sizeof(prefix) - 1; - if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) { - return &name[prefix_len]; + if (type == NODE_CALL) { + if (recv) { + switch (nd_type(recv)) { + case NODE_VCALL: + if (recv->nd_mid == rb_intern("__builtin")) { + return name; + } + break; + default: break; + } + } } - else { - return NULL; + else if (type == NODE_VCALL || type == NODE_FCALL) { + if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) { + return &name[prefix_len]; + } } + return NULL; } static int @@ -7204,8 +7216,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co NODE *args_node = node->nd_args; if (UNLIKELY(iseq_has_builtin_function_table(iseq)) && - (type == NODE_VCALL || type == NODE_FCALL) && - (builtin_func = iseq_builtin_function_name(mid)) != NULL) { + (builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) { if (parent_block != NULL) { COMPILE_ERROR(iseq, line, "should not call builtins here."); diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 505a256ba8..ae6c3b3812 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -72,7 +72,7 @@ end def collect_builtin base, tree, name, bs, inlines, params = nil while tree - call = sep = mid = args = nil + call = recv = sep = mid = args = nil case tree.first when :def params = collect_params(tree[2]) @@ -93,6 +93,8 @@ def collect_builtin base, tree, name, bs, inlines, params = nil when :method_add_arg _, mid, (_, (_, args)) = tree case mid.first + when :call + _, recv, sep, mid = mid when :fcall _, mid = mid else @@ -102,12 +104,27 @@ def collect_builtin base, tree, name, bs, inlines, params = nil _, mid = tree when :command # FCALL _, mid, (_, args) = tree + when :call, :command_call # CALL + _, recv, sep, mid, (_, args) = tree end if mid raise "unknown sexp: #{mid.inspect}" unless mid.first == :@ident _, mid, (lineno,) = mid - if /\A__builtin_(.+)/ =~ mid - cfunc_name = func_name = $1 + if recv + func_name = nil + case recv.first + when :vcall + _, recv = recv + if recv.first == :@ident and recv[1] == "__builtin" + func_name = mid.to_s + end + end + collect_builtin(base, recv, name, bs, inlines) unless func_name + else + func_name = mid[/\A__builtin_(.+)/, 1] + end + if func_name + cfunc_name = func_name args.pop unless (args ||= []).last argc = args.size