Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1962,6 +1962,10 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
kw++;
node = node->nd_next;
}
if (kw > VM_CALL_KW_LEN_MAX) {
COMPILE_ERROR(ERROR_ARGS_AT(RNODE(args->kw_args)) "too many keyword parameters (%d, maximum is %d)",
kw, (int)VM_CALL_KW_LEN_MAX);
}
arg_size += kw;
keyword->bits_start = arg_size++;

Expand Down Expand Up @@ -5075,6 +5079,12 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
{
int len = 0;
VALUE key_index = node_hash_unique_key_index(iseq, RNODE_HASH(root_node), &len);

if (len > VM_CALL_KW_LEN_MAX) {
COMPILE_ERROR(ERROR_ARGS_AT(root_node) "too many keyword arguments (%d, maximum is %d)",
len, (int)VM_CALL_KW_LEN_MAX);
}

struct rb_callinfo_kwarg *kw_arg =
rb_xmalloc_mul_add(len, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg));
VALUE *keywords = kw_arg->keywords;
Expand Down Expand Up @@ -9600,7 +9610,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
int idx, level;

if (mid == idCall &&
if ((mid == idCall || mid == idAREF || mid == idYield || mid == idEqq) &&
nd_type_p(get_nd_recv(node), NODE_LVAR) &&
iseq_block_param_id_p(iseq, RNODE_LVAR(get_nd_recv(node))->nd_vid, &idx, &level)) {
ADD_INSN2(recv, get_nd_recv(node), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
Expand Down
1 change: 1 addition & 0 deletions defs/id.def
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ firstline, predefined = __LINE__+1, %[\
bt
bt_locations
call
yield
mesg
exception
locals
Expand Down
1 change: 1 addition & 0 deletions internal/basic_operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum ruby_basic_operators {
BOP_DEFAULT,
BOP_PACK,
BOP_INCLUDE_P,
BOP_YIELD,

BOP_LAST_
};
Expand Down
9 changes: 8 additions & 1 deletion internal/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,15 @@ VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
VALUE rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze);
VALUE rb_obj_dup_setup(VALUE obj, VALUE dup);
VALUE rb_immutable_obj_clone(int, VALUE *, VALUE);
VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID);
VALUE rb_check_convert_type_with_id_slow(VALUE,int,const char*,ID);
int rb_bool_expected(VALUE, const char *, int raise);

static inline VALUE
rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
{
if (RB_TYPE_P(val, type) && type != T_DATA) return val;
return rb_check_convert_type_with_id_slow(val, type, tname, method);
}
static inline void RBASIC_CLEAR_CLASS(VALUE obj);
static inline void RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass);
static inline void RBASIC_SET_CLASS(VALUE obj, VALUE klass);
Expand Down
1 change: 1 addition & 0 deletions lib/prism/lex_compat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def deconstruct_keys(keys) # :nodoc:
KEYWORD_DEFINED: :on_kw,
KEYWORD_DO: :on_kw,
KEYWORD_DO_BLOCK: :on_kw,
KEYWORD_DO_LAMBDA: :on_kw,
KEYWORD_DO_LOOP: :on_kw,
KEYWORD_ELSE: :on_kw,
KEYWORD_ELSIF: :on_kw,
Expand Down
19 changes: 2 additions & 17 deletions lib/prism/translation/parser/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class Lexer # :nodoc:
KEYWORD_DEFINED: :kDEFINED,
KEYWORD_DO: :kDO,
KEYWORD_DO_BLOCK: :kDO_BLOCK,
KEYWORD_DO_LAMBDA: :kDO_LAMBDA,
KEYWORD_DO_LOOP: :kDO_COND,
KEYWORD_END: :kEND,
KEYWORD_END_UPCASE: :klEND,
Expand Down Expand Up @@ -192,14 +193,6 @@ class Lexer # :nodoc:
EXPR_BEG = 0x1
EXPR_LABEL = 0x400

# It is used to determine whether `do` is of the token type `kDO` or
# `kDO_LAMBDA`.
#
# NOTE: In edge cases like `-> (foo = -> (bar) {}) do end`, please note
# that `kDO` is still returned instead of `kDO_LAMBDA`, which is
# expected: https://github.com/ruby/prism/pull/3046
LAMBDA_TOKEN_TYPES = Set.new([:kDO_LAMBDA, :tLAMBDA, :tLAMBEG])

# The `PARENTHESIS_LEFT` token in Prism is classified as either
# `tLPAREN` or `tLPAREN2` in the Parser gem. The following token types
# are listed as those classified as `tLPAREN`.
Expand All @@ -221,7 +214,7 @@ class Lexer # :nodoc:
# Heredocs are complex and require us to keep track of a bit of info to refer to later
HeredocData = Struct.new(:identifier, :common_whitespace, keyword_init: true)

private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL, :LAMBDA_TOKEN_TYPES, :LPAREN_CONVERSION_TOKEN_TYPES, :HeredocData
private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL, :LPAREN_CONVERSION_TOKEN_TYPES, :HeredocData

# The Parser::Source::Buffer that the tokens were lexed from.
attr_reader :source_buffer
Expand Down Expand Up @@ -269,14 +262,6 @@ def to_a
location = range(token.location.start_offset, token.location.end_offset)

case type
when :kDO
nearest_lambda_token = tokens.reverse_each.find do |token|
LAMBDA_TOKEN_TYPES.include?(token.first)
end

if nearest_lambda_token&.first == :tLAMBDA
type = :kDO_LAMBDA
end
when :tCHARACTER
value.delete_prefix!("?")
# Character literals behave similar to double-quoted strings. We can use the same escaping mechanism.
Expand Down
8 changes: 2 additions & 6 deletions object.c
Original file line number Diff line number Diff line change
Expand Up @@ -3358,13 +3358,9 @@ rb_check_convert_type(VALUE val, int type, const char *tname, const char *method

/*! \private */
VALUE
rb_check_convert_type_with_id(VALUE val, int type, const char *tname, ID method)
rb_check_convert_type_with_id_slow(VALUE val, int type, const char *tname, ID method)
{
VALUE v;

/* always convert T_DATA */
if (TYPE(val) == type && type != T_DATA) return val;
v = convert_type_with_id(val, tname, method, FALSE, -1);
VALUE v = convert_type_with_id(val, tname, method, FALSE, -1);
if (NIL_P(v)) return Qnil;
if (TYPE(v) != type) {
rb_cant_convert_invalid_return(val, tname, rb_id2name(method), v);
Expand Down
2 changes: 2 additions & 0 deletions prism/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ tokens:
comment: "defined?"
- name: KEYWORD_DO_BLOCK
comment: "do keyword for a block attached to a command"
- name: KEYWORD_DO_LAMBDA
comment: "do keyword that opens the body of a lambda literal"
- name: KEYWORD_DO_LOOP
comment: "do keyword for a predicate in a while, until, or for loop"
- name: KEYWORD_END_UPCASE
Expand Down
Loading