26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# File 'lib/fastruby/translator/modules/call.rb', line 26
def to_c_call(tree, repass_var = nil)
directive_code = directive(tree)
if directive_code
return directive_code
end
if tree[2] == :require
tree[2] = :fastruby_require
elsif tree[2] == :raise
args = tree[3]
return _raise(args[1],args[2])
end
recv = tree[1]
mname = tree[2]
args = tree[3]
block_pass_arg = args.find{|arg| if arg == :arglist
false
else
arg[0] == :block_pass
end}
if block_pass_arg
call_tree = tree.dup
call_tree[3] = args.select{|arg| if arg == :arglist
true
else
arg[0] != :block_pass
end
}
block_arguments_tree = s(:masgn, s(:array, s(:splat, s(:lasgn, :__xblock_arguments))))
block_tree = s(:call, block_pass_arg[1], :call, s(:arglist, s(:splat, s(:lvar, :__xblock_arguments))))
replace_iter_tree = s(:iter, call_tree, block_arguments_tree, block_tree).to_fastruby_sexp
return to_c(replace_iter_tree)
end
mname = :require_fastruby if mname == :require
argnum = args.size - 1
recv = recv || s(:self)
recvtype = infer_type(recv)
if args.size > 1
if args.last[0] == :splat
return protected_block(
inline_block(
"
VALUE array = #{to_c args.last[1]};
if (TYPE(array) != T_ARRAY) {
array = rb_ary_new4(1,&array);
}
int argc = #{args.size-2};
VALUE argv[#{args.size} + RARRAY(array)->len];
#{
i = -1
args[1..-2].map {|arg|
i = i + 1
"argv[#{i}] = #{to_c arg}"
}.join(";\n")
};
int array_len = RARRAY(array)->len;
int i;
for (i=0; i<array_len;i++) {
argv[argc] = rb_ary_entry(array,i);
argc++;
}
return rb_funcall2(#{to_c recv}, #{intern_num tree[2]}, argc, argv);
"
), true, repass_var)
end
end
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
if recvtype
address = nil
mobject = nil
inference_complete = true
signature = [recvtype]
args[1..-1].each do |arg|
argtype = infer_type(arg)
signature << argtype
unless argtype
inference_complete = false
end
end
if repass_var
= ","+repass_var
= ",VALUE " + repass_var
else
= ""
= ""
end
if argnum == 0
value_cast = "VALUE,VALUE,VALUE"
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
else
value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
end
else if argnum == 0
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
else
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
end
end end
|