GitHub

Original file line numberDiff line numberDiff line change

@@ -922,6 +922,11 @@ MRB_API struct RClass* mrb_define_module_under_id(mrb_state *mrb, struct RClass

922922

*/

923923

#define MRB_ARGS_BLOCK() ((mrb_aspec)1)

924924
925+

/**

926+

* Function does not accept a block (&nil)

927+

*/

928+

#define MRB_ARGS_NOBLOCK() ((mrb_aspec)(1 << 23))

929+
925930

/**

926931

* Function accepts any number of arguments

927932

*/

Original file line numberDiff line numberDiff line change

@@ -69,7 +69,7 @@ OPCODE(CALL, Z) /* self.call(*, **, &) (But overlay the current cal

6969

OPCODE(BLKCALL, BB) /* R[a] = R[a].call(R[a+1],... ,R[a+b]); direct block call */

7070

OPCODE(SUPER, BB) /* R[a] = super(R[a+1],... ,R[a+b+1]) */

7171

OPCODE(ARGARY, BS) /* R[a] = argument array (16=m5:r1:m5:d1:lv4) */

72-

OPCODE(ENTER, W) /* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */

72+

OPCODE(ENTER, W) /* arg setup according to flags (24=n1:m5:o5:r1:m5:k5:d1:b1) */

7373

OPCODE(KEY_P, BB) /* R[a] = kdict.key?(Syms[b]) */

7474

OPCODE(KEYEND, Z) /* raise unless kdict.empty? */

7575

OPCODE(KARG, BB) /* R[a] = kdict[Syms[b]]; kdict.delete(Syms[b]) */

Original file line numberDiff line numberDiff line change

@@ -72,6 +72,7 @@ struct RProc {

7272

#define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f)

7373

#define MRB_ASPEC_KDICT(a) (((a) >> 1) & 0x1)

7474

#define MRB_ASPEC_BLOCK(a) ((a) & 1)

75+

#define MRB_ASPEC_NOBLOCK(a) (((a) >> 23) & 0x1)

7576
7677

#define MRB_PROC_CFUNC_FL 128

7778

#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC_FL) != 0)

Original file line numberDiff line numberDiff line change

@@ -2401,13 +2401,16 @@ lambda_body(codegen_scope *s, node *locals, struct mrb_ast_args *args, node *bod

24012401

/* keyword arguments */

24022402

ka = args->keyword_args ? node_len(args->keyword_args) : 0;

24032403

kd = args->kwrest_arg ? 1 : 0;

2404-

ba = args->block_arg ? 1 : 0;

2404+

/* &nil: no block accepted (noblock flag in aspec) */

2405+

mrb_bool noblock = args->block_arg == MRB_SYM(nil);

2406+

ba = (args->block_arg && !noblock) ? 1 : 0;

24052407
24062408

if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {

24072409

codegen_error(s, "too many formal arguments");

24082410

}

2409-

/* (23bits = 5:5:1:5:5:1:1) */

2410-

a = MRB_ARGS_REQ(ma)

2411+

/* (24bits = 1:5:5:1:5:5:1:1) */

2412+

a = (noblock ? MRB_ARGS_NOBLOCK() : 0)

2413+

| MRB_ARGS_REQ(ma)

24112414

| MRB_ARGS_OPT(oa)

24122415

| (ra ? MRB_ARGS_REST() : 0)

24132416

| MRB_ARGS_POST(pa)

Original file line numberDiff line numberDiff line change

@@ -1215,7 +1215,7 @@ new_args_tail(parser_state *p, node *kws, mrb_sym kwrest, mrb_sym blk)

12151215

}

12161216
12171217

local_add_blk(p);

1218-

if (blk) local_add_f(p, blk);

1218+

if (blk && blk != MRB_SYM(nil)) local_add_f(p, blk);

12191219
12201220

/* allocate register for keywords arguments */

12211221

/* order is for Proc#parameters */

@@ -4861,6 +4861,10 @@ f_block_arg : blkarg_mark tIDENTIFIER

48614861

{

48624862

$$ = $2;

48634863

}

4864+

| blkarg_mark keyword_nil

4865+

{

4866+

$$ = MRB_SYM(nil);

4867+

}

48644868

| blkarg_mark

48654869

{

48664870

$$ = intern_op(and);

@@ -8047,6 +8051,8 @@ dump_args(mrb_state *mrb, struct mrb_ast_args *args, int offset, uint16_t lineno

80478051

dump_prefix(offset, lineno);

80488052

if (blk == MRB_OPSYM(and))

80498053

printf("blk=&\n");

8054+

else if (blk == MRB_SYM(nil))

8055+

printf("blk=&nil\n");

80508056

else

80518057

printf("blk=&%s\n", mrb_sym_name(mrb, blk));

80528058

}

Original file line numberDiff line numberDiff line change

@@ -374,14 +374,15 @@ codedump(mrb_state *mrb, const mrb_irep *irep, FILE *out)

374374

print_lv_a(mrb, irep, a, out);

375375

break;

376376

CASE(OP_ENTER, W):

377-

fprintf(out, "ENTER\t\t%d:%d:%d:%d:%d:%d:%d (0x%x)\n",

377+

fprintf(out, "ENTER\t\t%d:%d:%d:%d:%d:%d:%d:%d (0x%x)\n",

378378

MRB_ASPEC_REQ(a),

379379

MRB_ASPEC_OPT(a),

380380

MRB_ASPEC_REST(a),

381381

MRB_ASPEC_POST(a),

382382

MRB_ASPEC_KEY(a),

383383

MRB_ASPEC_KDICT(a),

384-

MRB_ASPEC_BLOCK(a), a);

384+

MRB_ASPEC_BLOCK(a),

385+

MRB_ASPEC_NOBLOCK(a), a);

385386

break;

386387

CASE(OP_KEY_P, BB):

387388

fprintf(out, "KEY_P\t\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b]));

Original file line numberDiff line numberDiff line change

@@ -2558,6 +2558,12 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq

25582558
25592559

mrb_value * const argv0 = argv;

25602560

mrb_value blk = regs[ci_bidx(ci)];

2561+
2562+

/* &nil: reject block */

2563+

if (MRB_ASPEC_NOBLOCK(a) && !mrb_nil_p(blk)) {

2564+

RAISE_LIT(mrb, E_ARGUMENT_ERROR, "no block accepted");

2565+

}

2566+
25612567

mrb_value kdict = mrb_nil_value();

25622568
25632569

/* keyword arguments */

Read the original on github.com ↗