node/lib/metasm/samples/dynamic_ruby.rb
def optimize_call_static(ast, scope, want_value)
		arity = method_arity(ast[2]) rescue return
		if ast[2].to_s == @meth.to_s
			# self is recursive
			fptr = @cur_cfunc
		else
			fptr = get_cfuncptr(@klass, ast[2], @meth_singleton)
			return if not fptr
		end

		c_arglist = []

		if not ast[3]
			args = []
		elsif ast[3][0] == :array
			args = ast[3][1..-1]
		elsif ast[3][0] == :splat
			args = ast_to_c(ast[3], scope)
			if arity != -2 and !args.kind_of?(C::Variable)
				tmp = get_new_tmp_var('arg')
				scope.statements << C::CExpression[tmp, :'=', args]
				args = tmp
			end
			case arity
			when -2
				c_arglist << rb_self << args
			when -1
				c_arglist << [rb_ary_len(args)] << rb_ary_ptr(args) << rb_self
			else
				cnd = C::CExpression[rb_ary_len(args), :'!=', [arity]]
				scope.statements << C::If.new(cnd, rb_raise("#{arity} args expected", 'rb_eArgumentError'), nil)

				c_arglist << rb_self
				arity.times { |i| c_arglist << rb_ary_ptr(args, i) }
			end
			arity = :canttouchthis
		else return	# TODO
		end

		case arity
		when :canttouchthis
		when -2
			arg = get_new_tmp_var('arg')
			scope.statements << C::CExpression[arg, :'=', fcall('rb_ary_new')]
			args.each { |a|
				scope.statements << fcall('rb_ary_push', arg, ast_to_c(a, scope))
			}
			c_arglist << rb_self << arg

		when -1
			case args.length
			when 0
				argv = C::CExpression[[0], C::Pointer.new(value)]
			when 1
				val = ast_to_c(args[0], scope)
				if not val.kind_of? C::Variable
					argv = get_new_tmp_var('argv')
					scope.statements << C::CExpression[argv, :'=', val]
					val = argv
				end
				argv = C::CExpression[:'&', val]
			else
				argv = get_new_tmp_var('argv')
				argv.type = C::Array.new(value, args.length)
				args.each_with_index { |a, i|
					val = ast_to_c(a, scope)
					scope.statements << C::CExpression[[argv, :'[]', [i]], :'=', val]
				}
			end
			c_arglist << [args.length] << argv << rb_self

		else
			c_arglist << rb_self
			args.each { |a|
				va = get_new_tmp_var('arg')
				val = ast_to_c(a, scope, va)
				scope.statements << C::CExpression[va, :'=', val] if val != va
				c_arglist << va
			}
		end

		f = C::CExpression[fptr, :funcall, c_arglist]
		if want_value
			ret = get_new_tmp_var('ccall', want_value)
			scope.statements << C::CExpression[ret, :'=', f]
			ret
		else
			scope.statements << f
		end
	end
# call C funcs directly
# assume private function calls are not virtual and hardlink them here
call C funcs directly
assume private function calls are not virtual and hardlink them here
call C funcs directly assume private function calls are not virtual and hardlink them here
def optimize_call_static(ast, scope, want_value)
		arity = method_arity(ast[2]) rescue return
		if ast[2].to_s == @meth.to_s
			fptr = @cur_cfunc
		else
			fptr = get_cfuncptr(@klass, ast[2], @meth_singleton)
			return if not fptr
		end
		c_arglist = []
		if not ast[3]
			args = []
		elsif ast[3][0] == :array
			args = ast[3][1..-1]
		elsif ast[3][0] == :splat
			args = ast_to_c(ast[3], scope)
			if arity != -2 and !args.kind_of?(C::Variable)
				tmp = get_new_tmp_var('arg')
				scope.statements << C::CExpression[tmp, :'=', args]
				args = tmp
			end
			case arity
			when -2
				c_arglist << rb_self << args
			when -1
				c_arglist << [rb_ary_len(args)] << rb_ary_ptr(args) << rb_self
			else
				cnd = C::CExpression[rb_ary_len(args), :'!=', [arity]]
				scope.statements << C::If.new(cnd, rb_raise("#{arity} args expected", 'rb_eArgumentError'), nil)
				c_arglist << rb_self
				arity.times { |i| c_arglist << rb_ary_ptr(args, i) }
			end
			arity = :canttouchthis
		else return	
		end
		case arity
		when :canttouchthis
		when -2
			arg = get_new_tmp_var('arg')
			scope.statements << C::CExpression[arg, :'=', fcall('rb_ary_new')]
			args.each { |a|
				scope.statements << fcall('rb_ary_push', arg, ast_to_c(a, scope))
			}
			c_arglist << rb_self << arg
		when -1
			case args.length
			when 0
				argv = C::CExpression[[0], C::Pointer.new(value)]
			when 1
				val = ast_to_c(args[0], scope)
				if not val.kind_of? C::Variable
					argv = get_new_tmp_var('argv')
					scope.statements << C::CExpression[argv, :'=', val]
					val = argv
				end
				argv = C::CExpression[:'&', val]
			else
				argv = get_new_tmp_var('argv')
				argv.type = C::Array.new(value, args.length)
				args.each_with_index { |a, i|
					val = ast_to_c(a, scope)
					scope.statements << C::CExpression[[argv, :'[]', [i]], :'=', val]
				}
			end
			c_arglist << [args.length] << argv << rb_self
		else
			c_arglist << rb_self
			args.each { |a|
				va = get_new_tmp_var('arg')
				val = ast_to_c(a, scope, va)
				scope.statements << C::CExpression[va, :'=', val] if val != va
				c_arglist << va
			}
		end
		f = C::CExpression[fptr, :funcall, c_arglist]
		if want_value
			ret = get_new_tmp_var('ccall', want_value)
			scope.statements << C::CExpression[ret, :'=', f]
			ret
		else
			scope.statements << f
		end
	end
def optimize_call_static ( ast , scope , want_value ) arity = method_arity ( ast [ 2 ] ) rescue return if ast [ 2 ] . to_s == @meth . to_s fptr = @cur_cfunc else fptr = get_cfuncptr ( @klass , ast [ 2 ] , @meth_singleton ) return if not fptr end c_arglist = [ ] if not ast [ 3 ] args = [ ] elsif ast [ 3 ] [ 0 ] == :array args = ast [ 3 ] [ 1 .. - 1 ] elsif ast [ 3 ] [ 0 ] == :splat args = ast_to_c ( ast [ 3 ] , scope ) if arity != - 2 and ! args . kind_of? ( C :: Variable ) tmp = get_new_tmp_var ( 'arg' ) scope . statements << C :: CExpression [ tmp , :' = ' , args ] args = tmp end case arity when - 2 c_arglist << rb_self << args when - 1 c_arglist << [ rb_ary_len ( args ) ] << rb_ary_ptr ( args ) << rb_self else cnd = C :: CExpression [ rb_ary_len ( args ) , :' != ' , [ arity ] ] scope . statements << C :: If . new ( cnd , rb_raise ( "#{arity} args expected" , 'rb_eArgumentError' ) , nil ) c_arglist << rb_self arity . times { | i | c_arglist << rb_ary_ptr ( args , i ) } end arity = :canttouchthis else return end case arity when :canttouchthis when - 2 arg = get_new_tmp_var ( 'arg' ) scope . statements << C :: CExpression [ arg , :' = ' , fcall ( 'rb_ary_new' ) ] args . each { | a | scope . statements << fcall ( 'rb_ary_push' , arg , ast_to_c ( a , scope ) ) } c_arglist << rb_self << arg when - 1 case args . length when 0 argv = C :: CExpression [ [ 0 ] , C :: Pointer . new ( value ) ] when 1 val = ast_to_c ( args [ 0 ] , scope ) if not val . kind_of? C :: Variable argv = get_new_tmp_var ( 'argv' ) scope . statements << C :: CExpression [ argv , :' = ' , val ] val = argv end argv = C :: CExpression [ :' & ' , val ] else argv = get_new_tmp_var ( 'argv' ) argv . type = C :: Array . new ( value , args . length ) args . each_with_index { | a , i | val = ast_to_c ( a , scope ) scope . statements << C :: CExpression [ [ argv , :' [] ' , [ i ] ] , :' = ' , val ] } end c_arglist << [ args . length ] << argv << rb_self else c_arglist << rb_self args . each { | a | va = get_new_tmp_var ( 'arg' ) val = ast_to_c ( a , scope , va ) scope . statements << C :: CExpression [ va , :' = ' , val ] if val != va c_arglist << va } end f = C :: CExpression [ fptr , :funcall , c_arglist ] if want_value ret = get_new_tmp_var ( 'ccall' , want_value ) scope . statements << C :: CExpression [ ret , :' = ' , f ] ret else scope . statements << f end end
call C funcs directly
assume private function calls are not virtual and hardlink them here
call C funcs directly assume private function calls are not virtual and hardlink them here
# self is recursive # TODO
ast
scope
want_value