|
13 | 13 | import java.util.function.Function;
|
14 | 14 |
|
15 | 15 | import com.oracle.truffle.api.CompilerDirectives;
|
| 16 | +import com.oracle.truffle.api.source.SourceSection; |
16 | 17 | import org.truffleruby.RubyContext;
|
17 | 18 | import org.truffleruby.RubyLanguage;
|
| 19 | +import org.truffleruby.collections.CachedSupplier; |
18 | 20 | import org.truffleruby.core.array.ArrayUtils;
|
19 | 21 | import org.truffleruby.core.cast.TaintResultNode;
|
20 | 22 | import org.truffleruby.core.klass.RubyClass;
|
|
24 | 26 | import org.truffleruby.core.numeric.FixnumLowerNodeGen;
|
25 | 27 | import org.truffleruby.core.string.StringUtils;
|
26 | 28 | import org.truffleruby.core.support.TypeNodes;
|
27 |
| -import org.truffleruby.language.LazyRubyNode; |
28 | 29 | import org.truffleruby.language.LexicalScope;
|
29 | 30 | import org.truffleruby.language.NotProvided;
|
30 | 31 | import org.truffleruby.language.RubyNode;
|
@@ -121,118 +122,117 @@ private RubyClass getSingletonClass(Object object) {
|
121 | 122 | }
|
122 | 123 |
|
123 | 124 | private void addCoreMethod(RubyModule module, MethodDetails methodDetails) {
|
124 |
| - final CoreMethod method = methodDetails.getMethodAnnotation(); |
| 125 | + final CoreMethod annotation = methodDetails.getMethodAnnotation(); |
125 | 126 |
|
126 |
| - final String[] names = method.names(); |
| 127 | + final String[] names = annotation.names(); |
127 | 128 | assert names.length >= 1;
|
128 | 129 |
|
129 |
| - final Visibility visibility = method.visibility(); |
130 |
| - verifyUsage(module, methodDetails, method, visibility); |
| 130 | + final Visibility visibility = annotation.visibility(); |
| 131 | + verifyUsage(module, methodDetails, annotation, visibility); |
| 132 | + |
| 133 | + final String keywordAsOptional = annotation.keywordAsOptional().isEmpty() |
| 134 | + ? null |
| 135 | + : annotation.keywordAsOptional(); |
| 136 | + final Arity arity = createArity( |
| 137 | + annotation.required(), |
| 138 | + annotation.optional(), |
| 139 | + annotation.rest(), |
| 140 | + keywordAsOptional); |
| 141 | + final NodeFactory<? extends RubyNode> nodeFactory = methodDetails.getNodeFactory(); |
| 142 | + final boolean onSingleton = annotation.onSingleton() || annotation.constructor(); |
| 143 | + final boolean isModuleFunc = annotation.isModuleFunction(); |
| 144 | + final Split split = context.getOptions().CORE_ALWAYS_CLONE ? Split.ALWAYS : annotation.split(); |
131 | 145 |
|
132 |
| - final String keywordAsOptional = method.keywordAsOptional().isEmpty() ? null : method.keywordAsOptional(); |
133 |
| - final Arity arity = createArity(method.required(), method.optional(), method.rest(), keywordAsOptional); |
| 146 | + final Function<SharedMethodInfo, RootCallTarget> callTargetFactory = sharedMethodInfo -> { |
| 147 | + final RubyNode methodNode = createCoreMethodNode(nodeFactory, annotation, sharedMethodInfo); |
| 148 | + return createCallTarget(context, sharedMethodInfo, methodNode, split); |
| 149 | + }; |
134 | 150 |
|
135 |
| - final NodeFactory<? extends RubyNode> nodeFactory = methodDetails.getNodeFactory(); |
136 |
| - final Function<SharedMethodInfo, RubyNode> methodNodeFactory = sharedMethodInfo -> createCoreMethodNode( |
137 |
| - nodeFactory, |
138 |
| - method, |
139 |
| - sharedMethodInfo); |
140 |
| - |
141 |
| - final boolean onSingleton = method.onSingleton() || method.constructor(); |
142 |
| - addMethods( |
143 |
| - module, |
144 |
| - method.isModuleFunction(), |
145 |
| - onSingleton, |
146 |
| - names, |
147 |
| - arity, |
148 |
| - visibility, |
149 |
| - methodNodeFactory, |
150 |
| - method.split()); |
| 151 | + addMethods(module, isModuleFunc, onSingleton, names, arity, visibility, callTargetFactory); |
151 | 152 | }
|
152 | 153 |
|
153 |
| - public void addLazyCoreMethod(String nodeFactoryName, String moduleName, boolean isClass, Visibility visibility, |
154 |
| - boolean isModuleFunction, boolean onSingleton, |
155 |
| - Split split, int required, int optional, boolean rest, String keywordAsOptional, String... names) { |
| 154 | + public void addLazyCoreMethod( |
| 155 | + String nodeFactoryName, |
| 156 | + String moduleName, |
| 157 | + boolean isClass, |
| 158 | + Visibility visibility, |
| 159 | + boolean isModuleFunc, |
| 160 | + boolean onSingleton, |
| 161 | + Split split, |
| 162 | + int required, |
| 163 | + int optional, |
| 164 | + boolean rest, |
| 165 | + String keywordAsOptional, |
| 166 | + String... names) { |
| 167 | + |
156 | 168 | final RubyModule module = getModule(moduleName, isClass);
|
157 | 169 | final Arity arity = createArity(required, optional, rest, keywordAsOptional);
|
| 170 | + final Split finalSplit = context.getOptions().CORE_ALWAYS_CLONE ? Split.ALWAYS : split; |
158 | 171 |
|
159 |
| - Function<SharedMethodInfo, RubyNode> methodNodeFactory = sharedMethodInfo -> new LazyRubyNode(language, () -> { |
| 172 | + final Function<SharedMethodInfo, RootCallTarget> callTargetFactory = sharedMethodInfo -> { |
160 | 173 | final NodeFactory<? extends RubyNode> nodeFactory = loadNodeFactory(nodeFactoryName);
|
161 |
| - final CoreMethod methodAnnotation = nodeFactory.getNodeClass().getAnnotation(CoreMethod.class); |
162 |
| - return createCoreMethodNode(nodeFactory, methodAnnotation, sharedMethodInfo); |
163 |
| - }); |
| 174 | + final CoreMethod annotation = nodeFactory.getNodeClass().getAnnotation(CoreMethod.class); |
| 175 | + final RubyNode methodNode = createCoreMethodNode(nodeFactory, annotation, sharedMethodInfo); |
| 176 | + return createCallTarget(context, sharedMethodInfo, methodNode, finalSplit); |
| 177 | + }; |
164 | 178 |
|
165 |
| - addMethods(module, isModuleFunction, onSingleton, names, arity, visibility, methodNodeFactory, split); |
| 179 | + addMethods(module, isModuleFunc, onSingleton, names, arity, visibility, callTargetFactory); |
166 | 180 | }
|
167 | 181 |
|
168 |
| - private void addMethods(RubyModule module, boolean isModuleFunction, boolean onSingleton, String[] names, |
169 |
| - Arity arity, Visibility visibility, |
170 |
| - Function<SharedMethodInfo, RubyNode> methodNodeFactory, Split split) { |
| 182 | + private void addMethods( |
| 183 | + RubyModule module, |
| 184 | + boolean isModuleFunction, |
| 185 | + boolean onSingleton, |
| 186 | + String[] names, |
| 187 | + Arity arity, |
| 188 | + Visibility visibility, |
| 189 | + Function<SharedMethodInfo, RootCallTarget> callTargetFactory) { |
171 | 190 | if (isModuleFunction) {
|
172 |
| - addMethod(context, module, methodNodeFactory, names, Visibility.PRIVATE, arity, split); |
173 |
| - addMethod( |
174 |
| - context, |
175 |
| - getSingletonClass(module), |
176 |
| - methodNodeFactory, |
177 |
| - names, |
178 |
| - Visibility.PUBLIC, |
179 |
| - arity, |
180 |
| - split); |
| 191 | + addMethod(context, module, callTargetFactory, names, arity, Visibility.PRIVATE); |
| 192 | + addMethod(context, getSingletonClass(module), callTargetFactory, names, arity, Visibility.PUBLIC); |
181 | 193 | } else if (onSingleton) {
|
182 |
| - addMethod(context, getSingletonClass(module), methodNodeFactory, names, visibility, arity, split); |
| 194 | + addMethod(context, getSingletonClass(module), callTargetFactory, names, arity, visibility); |
183 | 195 | } else {
|
184 |
| - addMethod(context, module, methodNodeFactory, names, visibility, arity, split); |
| 196 | + addMethod(context, module, callTargetFactory, names, arity, visibility); |
185 | 197 | }
|
186 | 198 | }
|
187 | 199 |
|
188 |
| - private static void addMethod(RubyContext context, RubyModule module, |
189 |
| - Function<SharedMethodInfo, RubyNode> methodNodeFactory, String[] names, Visibility originalVisibility, |
| 200 | + private static void addMethod( |
| 201 | + RubyContext context, |
| 202 | + RubyModule module, |
| 203 | + Function<SharedMethodInfo, RootCallTarget> callTargetFactory, |
| 204 | + String[] names, |
190 | 205 | Arity arity,
|
191 |
| - Split split) { |
| 206 | + Visibility visibility) { |
| 207 | + |
192 | 208 | final LexicalScope lexicalScope = new LexicalScope(context.getRootLexicalScope(), module);
|
193 | 209 |
|
194 | 210 | for (String name : names) {
|
195 |
| - Visibility visibility = originalVisibility; |
196 |
| - if (ModuleOperations.isMethodPrivateFromName(name)) { |
197 |
| - visibility = Visibility.PRIVATE; |
198 |
| - } |
199 | 211 | final SharedMethodInfo sharedMethodInfo = makeSharedMethodInfo(context, lexicalScope, module, name, arity);
|
200 |
| - final RubyNode methodNode = methodNodeFactory.apply(sharedMethodInfo); |
201 |
| - split = context.getOptions().CORE_ALWAYS_CLONE ? Split.ALWAYS : split; |
202 |
| - final RootCallTarget callTarget = createCallTarget(context, sharedMethodInfo, methodNode, split); |
203 |
| - final InternalMethod method = new InternalMethod( |
| 212 | + |
| 213 | + module.fields.addMethod(context, null, new InternalMethod( |
204 | 214 | context,
|
205 | 215 | sharedMethodInfo,
|
206 | 216 | sharedMethodInfo.getLexicalScope(),
|
207 | 217 | DeclarationContext.NONE,
|
208 | 218 | name,
|
209 | 219 | module,
|
210 |
| - visibility, |
211 |
| - callTarget); |
212 |
| - |
213 |
| - module.fields.addMethod(context, null, method); |
| 220 | + ModuleOperations.isMethodPrivateFromName(name) ? Visibility.PRIVATE : visibility, |
| 221 | + null, |
| 222 | + new CachedSupplier<>(() -> callTargetFactory.apply(sharedMethodInfo)))); |
214 | 223 | }
|
215 | 224 | }
|
216 | 225 |
|
217 | 226 | private static SharedMethodInfo makeSharedMethodInfo(RubyContext context, LexicalScope lexicalScope,
|
218 | 227 | RubyModule module, String name, Arity arity) {
|
219 |
| - return new SharedMethodInfo( |
220 |
| - context.getCoreLibrary().sourceSection, |
221 |
| - lexicalScope, |
222 |
| - arity, |
223 |
| - module, |
224 |
| - name, |
225 |
| - 0, |
226 |
| - "builtin", |
227 |
| - null); |
| 228 | + final SourceSection sourceSection = context.getCoreLibrary().sourceSection; |
| 229 | + return new SharedMethodInfo(sourceSection, lexicalScope, arity, module, name, 0, "builtin", null); |
228 | 230 | }
|
229 | 231 |
|
230 | 232 | private static Arity createArity(int required, int optional, boolean rest, String keywordAsOptional) {
|
231 |
| - if (keywordAsOptional == null) { |
232 |
| - return new Arity(required, optional, rest); |
233 |
| - } else { |
234 |
| - return new Arity(required, optional, rest, 0, new String[]{ keywordAsOptional }, true, false); |
235 |
| - } |
| 233 | + return keywordAsOptional == null |
| 234 | + ? new Arity(required, optional, rest) |
| 235 | + : new Arity(required, optional, rest, 0, new String[]{ keywordAsOptional }, true, false); |
236 | 236 | }
|
237 | 237 |
|
238 | 238 | private static RootCallTarget createCallTarget(RubyContext context, SharedMethodInfo sharedMethodInfo,
|
|
0 commit comments