Class: Ruby2CExtension::CFunction::Block

Inherits:
Base
  • Object
show all
Defined in:
lib/ruby2cext/c_function.rb

Constant Summary

Constants included from Ruby2CExtension::CommonNodeComp

Ruby2CExtension::CommonNodeComp::NON_ITER_PROC

Instance Attribute Summary

Attributes inherited from Base

#closure_tbl, #compiler, #need_class, #need_cref, #need_res, #need_self, #need_wrap, #scope

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#add_closure_need, #add_helper, #assign_res, #closure_buid_c_code, #comp_retry, #comp_return, #get_cbase, #get_class, #get_closure_ary_var, #get_cref, #get_cvar_cbase, #get_lines, #get_self, #get_wrap_ptr, #global_const, #global_var, #in_while?, #initialize, #l, #pop_while, #push_while, #return_allowed?, #sym, #un, #wrap_buid_c_code

Methods included from Tools::EnsureNodeTypeMixin

#ensure_node_type

Methods included from Ruby2CExtension::CommonNodeComp

#build_args, #build_c_arr, #c_else, #c_for, #c_if, #c_scope, #c_scope_res, #c_static_once, #comp, #comp_alias, #comp_and, #comp_argscat, #comp_argspush, #comp_array, #comp_attrasgn, #comp_back_ref, #comp_begin, #comp_block, #comp_block_pass, #comp_call, #comp_case, #comp_cdecl, #comp_class, #comp_colon2, #comp_colon3, #comp_const, #comp_cvar, #comp_cvasgn, #comp_cvdecl, #comp_dasgn, #comp_dasgn_curr, #comp_defined, #comp_defn, #comp_defs, #comp_dot2, #comp_dot3, #comp_dregx, #comp_dregx_once, #comp_dstr, #comp_dsym, #comp_dvar, #comp_dxstr, #comp_ensure, #comp_evstr, #comp_false, #comp_fcall, #comp_flip2, #comp_flip3, #comp_for, #comp_gasgn, #comp_gvar, #comp_hash, #comp_iasgn, #comp_if, #comp_iter, #comp_ivar, #comp_lasgn, #comp_lit, #comp_lvar, #comp_masgn, #comp_match, #comp_match2, #comp_match3, #comp_module, #comp_nil, #comp_not, #comp_nth_ref, #comp_op_asgn1, #comp_op_asgn2, #comp_op_asgn_and, #comp_op_asgn_or, #comp_or, #comp_postexe, #comp_rescue, #comp_retry, #comp_return, #comp_sclass, #comp_self, #comp_splat, #comp_str, #comp_super, #comp_svalue, #comp_to_ary, #comp_true, #comp_undef, #comp_until, #comp_valias, #comp_vcall, #comp_when, #comp_while, #comp_xstr, #comp_yield, #comp_zarray, #comp_zsuper, #do_funcall, #get_global_entry, #handle_assign, #handle_dot, #handle_dyn_str, #handle_flip, #handle_iter, #handle_method_args, #handle_when, #helper_class_module_check, #helper_super_allowed_check, #make_block, #make_class_prefix

Constructor Details

This class inherits a constructor from Ruby2CExtension::CFunction::Base

Class Method Details

.compile(outer, block_node, var_node) ⇒ Object



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'lib/ruby2cext/c_function.rb', line 330

def self.compile(outer, block_node, var_node)
	ensure_node_type(block_node, :block)
	cf = self.new(outer.compiler, outer.scope.new_dyna_scope)
	cf.instance_eval {
		if Array === var_node
			if var_node.first == :masgn
				dup_hash = var_node.last.dup
				c_if("ruby_current_node->nd_state != 1") { # 1 is YIELD_FUNC_AVALUE
					# do "svalue_to_mrhs"
					c_if("bl_val == Qundef") {
						l "bl_val = rb_ary_new2(0);"
					}
					c_else {
						#if dup_hash[:head] # TODO
							l "VALUE tmp = rb_check_array_type(bl_val);"
							l "bl_val = (NIL_P(tmp) ? rb_ary_new3(1, bl_val) : tmp);"
						#else
						#	l "bl_val = rb_ary_new3(1, bl_val);"
						#end
					}
				}
				dup_hash[:value] = "bl_val"
				comp_masgn(dup_hash)
			else
				c_if("ruby_current_node->nd_state == 1") { # 1 is YIELD_FUNC_AVALUE
					# do "avalue_to_svalue"
					l "if (RARRAY(bl_val)->len == 0) bl_val = Qnil;"
					l "else if (RARRAY(bl_val)->len == 1) bl_val = RARRAY(bl_val)->ptr[0];"
				}
				handle_assign(var_node, "bl_val")
			end
		end
		l "block_redo:"
		l "return #{comp_block(block_node.last)};"
	}
	body = "#{cf.init_c_code(outer)}\n#{cf.get_lines}"
	sig = "static VALUE FUNNAME(VALUE bl_val, VALUE closure_ary, VALUE bl_self) {"
	fname = cf.compiler.add_fun("#{sig}\n#{body}\n}", "block")
	[fname, cf.need_closure_ptr]
end

Instance Method Details

#break_allowed?(with_value) ⇒ Boolean

Returns:

  • (Boolean)


396
397
398
# File 'lib/ruby2cext/c_function.rb', line 396

def break_allowed?(with_value)
	super || !with_value
end

#comp_break(hash) ⇒ Object



399
400
401
402
403
404
405
406
407
# File 'lib/ruby2cext/c_function.rb', line 399

def comp_break(hash)
	if in_while?(:break)
		super
	else
		raise Ruby2CExtError::NotSupported, "break with a value is not supported in a block" if hash[:stts]
		l "rb_iter_break();"
		"Qnil"
	end
end

#comp_next(hash) ⇒ Object



412
413
414
415
416
417
418
419
# File 'lib/ruby2cext/c_function.rb', line 412

def comp_next(hash)
	if in_while?(:next)
		super
	else
		l "return #{comp(hash[:stts])};"
		"Qnil"
	end
end

#comp_redo(hash) ⇒ Object



424
425
426
427
428
429
430
431
# File 'lib/ruby2cext/c_function.rb', line 424

def comp_redo(hash)
	if in_while?(:redo)
		super
	else
		l "goto block_redo;"
		"Qnil"
	end
end

#get_cref_implObject



437
438
439
# File 'lib/ruby2cext/c_function.rb', line 437

def get_cref_impl
	"cref"
end

#init_c_code(outer) ⇒ Object



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/ruby2cext/c_function.rb', line 371

def init_c_code(outer)
	cb_c_code = closure_buid_c_code # must be called before the rest because it might change self or scope
	outer.add_closure_need(:self) if need_self
	outer.add_closure_need(:class) if need_class
	outer.add_closure_need(:cref) if need_cref
	res = []
	res << "VALUE res;" if need_res
	if need_closure_ptr
		res << "VALUE *closure = RARRAY(closure_ary)->ptr;"
	end
	res << "VALUE self = (bl_self == Qundef ? closure[#{outer.closure_tbl.index(:self)}] : bl_self);" if need_self
	res << "VALUE s_class = (bl_self == Qundef ? closure[#{outer.closure_tbl.index(:class)}] : ruby_class);" if need_class
	if need_cref
		# see #define Data_Get_Struct
		res << "NODE *cref = (Check_Type(closure[#{outer.closure_tbl.index(:cref)}]," +
			" T_DATA), (NODE*)DATA_PTR(closure[#{outer.closure_tbl.index(:cref)}]));"
	end
	res << "VALUE #{get_closure_ary_var};" if cb_c_code
	res << "struct wrap the_wrap;" if need_wrap
	res << scope.init_c_code
	res << cb_c_code if cb_c_code
	res << wrap_buid_c_code if need_wrap
	res.compact.join("\n")
end

#need_closure_ptrObject



433
434
435
# File 'lib/ruby2cext/c_function.rb', line 433

def need_closure_ptr
	scope.need_closure || need_self || need_class || need_cref
end

#next_allowed?Boolean

Returns:

  • (Boolean)


409
410
411
# File 'lib/ruby2cext/c_function.rb', line 409

def next_allowed?
	true
end

#redo_allowed?Boolean

Returns:

  • (Boolean)


421
422
423
# File 'lib/ruby2cext/c_function.rb', line 421

def redo_allowed?
	true
end