Class: Ruby2CExtension::CFunction::Block

Inherits:
Base 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



326
327
328
329
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
# File 'lib/ruby2cext/c_function.rb', line 326

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)


392
393
394
# File 'lib/ruby2cext/c_function.rb', line 392

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

#comp_break(hash) ⇒ Object



395
396
397
398
399
400
401
402
403
# File 'lib/ruby2cext/c_function.rb', line 395

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



408
409
410
411
412
413
414
415
# File 'lib/ruby2cext/c_function.rb', line 408

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

#comp_redo(hash) ⇒ Object



420
421
422
423
424
425
426
427
# File 'lib/ruby2cext/c_function.rb', line 420

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

#get_cref_implObject



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

def get_cref_impl
	"cref"
end

#init_c_code(outer) ⇒ Object



367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/ruby2cext/c_function.rb', line 367

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



429
430
431
# File 'lib/ruby2cext/c_function.rb', line 429

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

#next_allowed?Boolean

Returns:

  • (Boolean)


405
406
407
# File 'lib/ruby2cext/c_function.rb', line 405

def next_allowed?
	true
end

#redo_allowed?Boolean

Returns:

  • (Boolean)


417
418
419
# File 'lib/ruby2cext/c_function.rb', line 417

def redo_allowed?
	true
end