Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java @ 13529:856c2c294f84
Merge.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 07 Jan 2014 18:53:04 +0100 |
parents | 0fbee3eb71f0 |
children | f70c894ae874 |
comparison
equal
deleted
inserted
replaced
13528:5a0c694ef735 | 13529:856c2c294f84 |
---|---|
1 /* | |
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This | |
3 * code is released under a tri EPL/GPL/LGPL license. You can use it, | |
4 * redistribute it and/or modify it under the terms of the: | |
5 * | |
6 * Eclipse Public License version 1.0 | |
7 * GNU General Public License version 2 | |
8 * GNU Lesser General Public License version 2.1 | |
9 */ | |
10 package com.oracle.truffle.ruby.nodes.core; | |
11 | |
12 import java.util.*; | |
13 import java.util.regex.*; | |
14 | |
15 import com.oracle.truffle.api.*; | |
16 import com.oracle.truffle.api.dsl.*; | |
17 import com.oracle.truffle.api.frame.*; | |
18 import com.oracle.truffle.ruby.runtime.*; | |
19 import com.oracle.truffle.ruby.runtime.core.*; | |
20 import com.oracle.truffle.ruby.runtime.core.array.*; | |
21 | |
22 @CoreClass(name = "String") | |
23 public abstract class StringNodes { | |
24 | |
25 @CoreMethod(names = "+", minArgs = 1, maxArgs = 1) | |
26 public abstract static class AddNode extends CoreMethodNode { | |
27 | |
28 public AddNode(RubyContext context, SourceSection sourceSection) { | |
29 super(context, sourceSection); | |
30 } | |
31 | |
32 public AddNode(AddNode prev) { | |
33 super(prev); | |
34 } | |
35 | |
36 @Specialization | |
37 public RubyString add(RubyString a, RubyString b) { | |
38 return new RubyString(a.getRubyClass().getContext().getCoreLibrary().getStringClass(), a.toString() + b.toString()); | |
39 } | |
40 } | |
41 | |
42 @CoreMethod(names = {"==", "==="}, minArgs = 1, maxArgs = 1) | |
43 public abstract static class EqualNode extends CoreMethodNode { | |
44 | |
45 public EqualNode(RubyContext context, SourceSection sourceSection) { | |
46 super(context, sourceSection); | |
47 } | |
48 | |
49 public EqualNode(EqualNode prev) { | |
50 super(prev); | |
51 } | |
52 | |
53 @Specialization | |
54 public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) { | |
55 return false; | |
56 } | |
57 | |
58 @Specialization | |
59 public boolean equal(RubyString a, RubyString b) { | |
60 return a.toString().equals(b.toString()); | |
61 } | |
62 } | |
63 | |
64 @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1) | |
65 public abstract static class NotEqualNode extends CoreMethodNode { | |
66 | |
67 public NotEqualNode(RubyContext context, SourceSection sourceSection) { | |
68 super(context, sourceSection); | |
69 } | |
70 | |
71 public NotEqualNode(NotEqualNode prev) { | |
72 super(prev); | |
73 } | |
74 | |
75 @Specialization | |
76 public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) { | |
77 return true; | |
78 } | |
79 | |
80 @Specialization | |
81 public boolean notEqual(RubyString a, RubyString b) { | |
82 return !a.toString().equals(b.toString()); | |
83 } | |
84 | |
85 } | |
86 | |
87 @CoreMethod(names = "<=>", minArgs = 1, maxArgs = 1) | |
88 public abstract static class CompareNode extends CoreMethodNode { | |
89 | |
90 public CompareNode(RubyContext context, SourceSection sourceSection) { | |
91 super(context, sourceSection); | |
92 } | |
93 | |
94 public CompareNode(CompareNode prev) { | |
95 super(prev); | |
96 } | |
97 | |
98 @Specialization | |
99 public int compare(RubyString a, RubyString b) { | |
100 return a.toString().compareTo(b.toString()); | |
101 } | |
102 } | |
103 | |
104 @CoreMethod(names = "<<", minArgs = 1, maxArgs = 1) | |
105 public abstract static class ConcatNode extends CoreMethodNode { | |
106 | |
107 public ConcatNode(RubyContext context, SourceSection sourceSection) { | |
108 super(context, sourceSection); | |
109 } | |
110 | |
111 public ConcatNode(ConcatNode prev) { | |
112 super(prev); | |
113 } | |
114 | |
115 @Specialization | |
116 public RubyString concat(RubyString string, RubyString other) { | |
117 string.replace(string.toString() + other.toString()); | |
118 return string; | |
119 } | |
120 } | |
121 | |
122 @CoreMethod(names = "%", minArgs = 1, maxArgs = 1, isSplatted = true) | |
123 public abstract static class FormatNode extends CoreMethodNode { | |
124 | |
125 public FormatNode(RubyContext context, SourceSection sourceSection) { | |
126 super(context, sourceSection); | |
127 } | |
128 | |
129 public FormatNode(FormatNode prev) { | |
130 super(prev); | |
131 } | |
132 | |
133 @Specialization | |
134 public RubyString format(RubyString format, Object[] args) { | |
135 final RubyContext context = getContext(); | |
136 | |
137 if (args.length == 1 && args[0] instanceof RubyArray) { | |
138 return context.makeString(StringFormatter.format(format.toString(), ((RubyArray) args[0]).asList())); | |
139 } else { | |
140 return context.makeString(StringFormatter.format(format.toString(), Arrays.asList(args))); | |
141 } | |
142 } | |
143 } | |
144 | |
145 @CoreMethod(names = "[]", minArgs = 1, maxArgs = 2, isSplatted = true) | |
146 public abstract static class GetIndexNode extends CoreMethodNode { | |
147 | |
148 public GetIndexNode(RubyContext context, SourceSection sourceSection) { | |
149 super(context, sourceSection); | |
150 } | |
151 | |
152 public GetIndexNode(GetIndexNode prev) { | |
153 super(prev); | |
154 } | |
155 | |
156 @Specialization | |
157 public Object getIndex(RubyString string, Object[] args) { | |
158 return RubyString.getIndex(getContext(), string.toString(), args); | |
159 } | |
160 } | |
161 | |
162 @CoreMethod(names = "=~", minArgs = 1, maxArgs = 1) | |
163 public abstract static class MatchOperatorNode extends CoreMethodNode { | |
164 | |
165 public MatchOperatorNode(RubyContext context, SourceSection sourceSection) { | |
166 super(context, sourceSection); | |
167 } | |
168 | |
169 public MatchOperatorNode(MatchOperatorNode prev) { | |
170 super(prev); | |
171 } | |
172 | |
173 @Specialization | |
174 public Object match(VirtualFrame frame, RubyString string, RubyRegexp regexp) { | |
175 return regexp.matchOperator(frame, string.toString()); | |
176 } | |
177 } | |
178 | |
179 @CoreMethod(names = "chomp", maxArgs = 0) | |
180 public abstract static class ChompNode extends CoreMethodNode { | |
181 | |
182 public ChompNode(RubyContext context, SourceSection sourceSection) { | |
183 super(context, sourceSection); | |
184 } | |
185 | |
186 public ChompNode(ChompNode prev) { | |
187 super(prev); | |
188 } | |
189 | |
190 @Specialization | |
191 public RubyString chomp(RubyString string) { | |
192 return string.getRubyClass().getContext().makeString(string.toString().trim()); | |
193 } | |
194 } | |
195 | |
196 @CoreMethod(names = "chomp!", maxArgs = 0) | |
197 public abstract static class ChompBangNode extends CoreMethodNode { | |
198 | |
199 public ChompBangNode(RubyContext context, SourceSection sourceSection) { | |
200 super(context, sourceSection); | |
201 } | |
202 | |
203 public ChompBangNode(ChompBangNode prev) { | |
204 super(prev); | |
205 } | |
206 | |
207 @Specialization | |
208 public RubyString chompBang(RubyString string) { | |
209 string.replace(string.toString().trim()); | |
210 return string; | |
211 } | |
212 } | |
213 | |
214 @CoreMethod(names = "downcase", maxArgs = 0) | |
215 public abstract static class DowncaseNode extends CoreMethodNode { | |
216 | |
217 public DowncaseNode(RubyContext context, SourceSection sourceSection) { | |
218 super(context, sourceSection); | |
219 } | |
220 | |
221 public DowncaseNode(DowncaseNode prev) { | |
222 super(prev); | |
223 } | |
224 | |
225 @Specialization | |
226 public RubyString downcase(RubyString string) { | |
227 return string.getRubyClass().getContext().makeString(string.toString().toLowerCase()); | |
228 } | |
229 } | |
230 | |
231 @CoreMethod(names = "downcase!", maxArgs = 0) | |
232 public abstract static class DowncaseBangNode extends CoreMethodNode { | |
233 | |
234 public DowncaseBangNode(RubyContext context, SourceSection sourceSection) { | |
235 super(context, sourceSection); | |
236 } | |
237 | |
238 public DowncaseBangNode(DowncaseBangNode prev) { | |
239 super(prev); | |
240 } | |
241 | |
242 @Specialization | |
243 public RubyString downcase(RubyString string) { | |
244 string.replace(string.toString().toLowerCase()); | |
245 return string; | |
246 } | |
247 } | |
248 | |
249 @CoreMethod(names = "empty?", maxArgs = 0) | |
250 public abstract static class EmptyNode extends CoreMethodNode { | |
251 | |
252 public EmptyNode(RubyContext context, SourceSection sourceSection) { | |
253 super(context, sourceSection); | |
254 } | |
255 | |
256 public EmptyNode(EmptyNode prev) { | |
257 super(prev); | |
258 } | |
259 | |
260 @Specialization | |
261 public boolean empty(RubyString string) { | |
262 return string.toString().isEmpty(); | |
263 } | |
264 } | |
265 | |
266 @CoreMethod(names = "end_with?", minArgs = 1, maxArgs = 1) | |
267 public abstract static class EndWithNode extends CoreMethodNode { | |
268 | |
269 public EndWithNode(RubyContext context, SourceSection sourceSection) { | |
270 super(context, sourceSection); | |
271 } | |
272 | |
273 public EndWithNode(EndWithNode prev) { | |
274 super(prev); | |
275 } | |
276 | |
277 @Specialization | |
278 public boolean endWith(RubyString string, RubyString b) { | |
279 return string.toString().endsWith(b.toString()); | |
280 } | |
281 } | |
282 | |
283 @CoreMethod(names = "gsub", minArgs = 2, maxArgs = 2) | |
284 public abstract static class GsubNode extends CoreMethodNode { | |
285 | |
286 public GsubNode(RubyContext context, SourceSection sourceSection) { | |
287 super(context, sourceSection); | |
288 } | |
289 | |
290 public GsubNode(GsubNode prev) { | |
291 super(prev); | |
292 } | |
293 | |
294 @Specialization | |
295 public RubyString gsub(RubyString string, RubyString regexpString, RubyString replacement) { | |
296 final RubyRegexp regexp = new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), regexpString.toString()); | |
297 return gsub(string, regexp, replacement); | |
298 } | |
299 | |
300 @Specialization | |
301 public RubyString gsub(RubyString string, RubyRegexp regexp, RubyString replacement) { | |
302 return getContext().makeString(regexp.getPattern().matcher(string.toString()).replaceAll(replacement.toString())); | |
303 } | |
304 } | |
305 | |
306 @CoreMethod(names = "inspect", maxArgs = 0) | |
307 public abstract static class InpsectNode extends CoreMethodNode { | |
308 | |
309 public InpsectNode(RubyContext context, SourceSection sourceSection) { | |
310 super(context, sourceSection); | |
311 } | |
312 | |
313 public InpsectNode(InpsectNode prev) { | |
314 super(prev); | |
315 } | |
316 | |
317 @Specialization | |
318 public RubyString inspect(RubyString string) { | |
319 return getContext().makeString("\"" + string.toString().replace("\\", "\\\\").replace("\"", "\\\"") + "\""); | |
320 } | |
321 } | |
322 | |
323 @CoreMethod(names = "ljust", minArgs = 1, maxArgs = 2) | |
324 public abstract static class LjustNode extends CoreMethodNode { | |
325 | |
326 public LjustNode(RubyContext context, SourceSection sourceSection) { | |
327 super(context, sourceSection); | |
328 } | |
329 | |
330 public LjustNode(LjustNode prev) { | |
331 super(prev); | |
332 } | |
333 | |
334 @Specialization | |
335 public RubyString ljust(RubyString string, int length, @SuppressWarnings("unused") UndefinedPlaceholder padding) { | |
336 return getContext().makeString(RubyString.ljust(string.toString(), length, " ")); | |
337 } | |
338 | |
339 @Specialization | |
340 public RubyString ljust(RubyString string, int length, RubyString padding) { | |
341 return getContext().makeString(RubyString.ljust(string.toString(), length, padding.toString())); | |
342 } | |
343 | |
344 } | |
345 | |
346 @CoreMethod(names = "size", maxArgs = 0) | |
347 public abstract static class SizeNode extends CoreMethodNode { | |
348 | |
349 public SizeNode(RubyContext context, SourceSection sourceSection) { | |
350 super(context, sourceSection); | |
351 } | |
352 | |
353 public SizeNode(SizeNode prev) { | |
354 super(prev); | |
355 } | |
356 | |
357 @Specialization | |
358 public int size(RubyString string) { | |
359 return string.toString().length(); | |
360 } | |
361 } | |
362 | |
363 @CoreMethod(names = "match", minArgs = 1, maxArgs = 1) | |
364 public abstract static class MatchNode extends CoreMethodNode { | |
365 | |
366 public MatchNode(RubyContext context, SourceSection sourceSection) { | |
367 super(context, sourceSection); | |
368 } | |
369 | |
370 public MatchNode(MatchNode prev) { | |
371 super(prev); | |
372 } | |
373 | |
374 @Specialization | |
375 public Object match(RubyString string, RubyString regexpString) { | |
376 final RubyRegexp regexp = new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), regexpString.toString()); | |
377 return regexp.match(string.toString()); | |
378 } | |
379 | |
380 @Specialization | |
381 public Object match(RubyString string, RubyRegexp regexp) { | |
382 return regexp.match(string.toString()); | |
383 } | |
384 } | |
385 | |
386 @CoreMethod(names = "rjust", minArgs = 1, maxArgs = 2) | |
387 public abstract static class RjustNode extends CoreMethodNode { | |
388 | |
389 public RjustNode(RubyContext context, SourceSection sourceSection) { | |
390 super(context, sourceSection); | |
391 } | |
392 | |
393 public RjustNode(RjustNode prev) { | |
394 super(prev); | |
395 } | |
396 | |
397 @Specialization | |
398 public RubyString rjust(RubyString string, int length, @SuppressWarnings("unused") UndefinedPlaceholder padding) { | |
399 return getContext().makeString(RubyString.rjust(string.toString(), length, " ")); | |
400 } | |
401 | |
402 @Specialization | |
403 public RubyString rjust(RubyString string, int length, RubyString padding) { | |
404 return getContext().makeString(RubyString.rjust(string.toString(), length, padding.toString())); | |
405 } | |
406 | |
407 } | |
408 | |
409 @CoreMethod(names = "scan", minArgs = 1, maxArgs = 1) | |
410 public abstract static class ScanNode extends CoreMethodNode { | |
411 | |
412 public ScanNode(RubyContext context, SourceSection sourceSection) { | |
413 super(context, sourceSection); | |
414 } | |
415 | |
416 public ScanNode(ScanNode prev) { | |
417 super(prev); | |
418 } | |
419 | |
420 @Specialization | |
421 public RubyArray scan(RubyString string, RubyString regexp) { | |
422 return RubyString.scan(getContext(), string.toString(), Pattern.compile(regexp.toString())); | |
423 } | |
424 | |
425 @Specialization | |
426 public RubyArray scan(RubyString string, RubyRegexp regexp) { | |
427 return RubyString.scan(getContext(), string.toString(), regexp.getPattern()); | |
428 } | |
429 | |
430 } | |
431 | |
432 @CoreMethod(names = "split", minArgs = 1, maxArgs = 1) | |
433 public abstract static class SplitNode extends CoreMethodNode { | |
434 | |
435 public SplitNode(RubyContext context, SourceSection sourceSection) { | |
436 super(context, sourceSection); | |
437 } | |
438 | |
439 public SplitNode(SplitNode prev) { | |
440 super(prev); | |
441 } | |
442 | |
443 @Specialization | |
444 public RubyArray split(RubyString string, RubyString sep) { | |
445 final RubyContext context = getContext(); | |
446 | |
447 final String[] components = string.toString().split(Pattern.quote(sep.toString())); | |
448 | |
449 final Object[] objects = new Object[components.length]; | |
450 | |
451 for (int n = 0; n < objects.length; n++) { | |
452 objects[n] = context.makeString(components[n]); | |
453 } | |
454 | |
455 return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects); | |
456 } | |
457 | |
458 @Specialization | |
459 public RubyArray split(RubyString string, RubyRegexp sep) { | |
460 final RubyContext context = getContext(); | |
461 | |
462 final String[] components = string.toString().split(sep.getPattern().pattern()); | |
463 | |
464 final Object[] objects = new Object[components.length]; | |
465 | |
466 for (int n = 0; n < objects.length; n++) { | |
467 objects[n] = context.makeString(components[n]); | |
468 } | |
469 | |
470 return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects); | |
471 } | |
472 } | |
473 | |
474 @CoreMethod(names = "start_with?", minArgs = 1, maxArgs = 1) | |
475 public abstract static class StartWithNode extends CoreMethodNode { | |
476 | |
477 public StartWithNode(RubyContext context, SourceSection sourceSection) { | |
478 super(context, sourceSection); | |
479 } | |
480 | |
481 public StartWithNode(StartWithNode prev) { | |
482 super(prev); | |
483 } | |
484 | |
485 @Specialization | |
486 public boolean endWith(RubyString string, RubyString b) { | |
487 return string.toString().startsWith(b.toString()); | |
488 } | |
489 } | |
490 | |
491 @CoreMethod(names = "to_f", maxArgs = 0) | |
492 public abstract static class ToFNode extends CoreMethodNode { | |
493 | |
494 public ToFNode(RubyContext context, SourceSection sourceSection) { | |
495 super(context, sourceSection); | |
496 } | |
497 | |
498 public ToFNode(ToFNode prev) { | |
499 super(prev); | |
500 } | |
501 | |
502 @Specialization | |
503 public double toF(RubyString string) { | |
504 return Double.parseDouble(string.toString()); | |
505 } | |
506 } | |
507 | |
508 @CoreMethod(names = "to_i", maxArgs = 0) | |
509 public abstract static class ToINode extends CoreMethodNode { | |
510 | |
511 public ToINode(RubyContext context, SourceSection sourceSection) { | |
512 super(context, sourceSection); | |
513 } | |
514 | |
515 public ToINode(ToINode prev) { | |
516 super(prev); | |
517 } | |
518 | |
519 @Specialization | |
520 public Object toI(RubyString string) { | |
521 return string.toInteger(); | |
522 } | |
523 } | |
524 | |
525 @CoreMethod(names = "to_s", maxArgs = 0) | |
526 public abstract static class ToSNode extends CoreMethodNode { | |
527 | |
528 public ToSNode(RubyContext context, SourceSection sourceSection) { | |
529 super(context, sourceSection); | |
530 } | |
531 | |
532 public ToSNode(ToSNode prev) { | |
533 super(prev); | |
534 } | |
535 | |
536 @Specialization | |
537 public RubyString toF(RubyString string) { | |
538 return string; | |
539 } | |
540 } | |
541 | |
542 @CoreMethod(names = {"to_sym", "intern"}, maxArgs = 0) | |
543 public abstract static class ToSymNode extends CoreMethodNode { | |
544 | |
545 public ToSymNode(RubyContext context, SourceSection sourceSection) { | |
546 super(context, sourceSection); | |
547 } | |
548 | |
549 public ToSymNode(ToSymNode prev) { | |
550 super(prev); | |
551 } | |
552 | |
553 @Specialization | |
554 public RubySymbol toSym(RubyString string) { | |
555 return new RubySymbol(getContext().getCoreLibrary().getSymbolClass(), string.toString()); | |
556 } | |
557 } | |
558 | |
559 } |