comparison graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children f70c894ae874
comparison
equal deleted inserted replaced
13513:64a23ce736a0 13514:0fbee3eb71f0
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 }