1 package io.jawk.intermediate;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import java.io.Serializable;
26 import java.util.List;
27 import java.util.function.Supplier;
28 import java.util.regex.Pattern;
29 import io.jawk.ext.ExtensionFunction;
30
31
32
33
34
35
36
37
38
39 public abstract class Tuple implements Serializable {
40
41 private static final long serialVersionUID = 8105941219003992817L;
42 private final Opcode opcode;
43 private int lineNumber = -1;
44 private Tuple next = null;
45
46 Tuple(Opcode opcode) {
47 this.opcode = opcode;
48 }
49
50
51
52
53
54
55 public final Opcode getOpcode() {
56 return opcode;
57 }
58
59
60
61
62
63
64 public Address getAddress() {
65 return null;
66 }
67
68
69
70
71
72
73 public void touch(List<Tuple> queue) {
74 Address address = getAddress();
75 if (address == null) {
76 return;
77 }
78 if (address.index() == -1) {
79 throw new Error("address " + address + " is unresolved");
80 }
81 if (address.index() >= queue.size()) {
82 throw new Error("address " + address + " doesn't resolve to an actual list element");
83 }
84 }
85
86 boolean hasNext() {
87 return next != null;
88 }
89
90
91
92
93
94
95 Tuple getNext() {
96 return next;
97 }
98
99 void setNext(Tuple next) {
100 this.next = next;
101 }
102
103 void setLineNumber(int lineNumber) {
104 this.lineNumber = lineNumber;
105 }
106
107
108
109
110
111
112 public int getLineNumber() {
113 return lineNumber;
114 }
115
116 private static String stringArgument(String value) {
117 return ", \"" + value + '"';
118 }
119
120 private static String patternArgument(Pattern pattern) {
121 return ", /" + (pattern == null ? "" : pattern.pattern()) + '/';
122 }
123
124
125
126
127 public static class NoOperandTuple extends Tuple {
128 private static final long serialVersionUID = 1L;
129
130 NoOperandTuple(Opcode opcode) {
131 super(opcode);
132 }
133
134 @Override
135 public String toString() {
136 return getOpcode().name();
137 }
138 }
139
140
141
142
143 public static final class BuiltinVarTuple extends NoOperandTuple {
144 private static final long serialVersionUID = 1L;
145
146 BuiltinVarTuple(Opcode opcode) {
147 super(opcode);
148 }
149 }
150
151
152
153
154 public static final class PushLongTuple extends Tuple {
155 private static final long serialVersionUID = 1L;
156 private final long value;
157
158 PushLongTuple(long value) {
159 super(Opcode.PUSH_LONG);
160 this.value = value;
161 }
162
163
164
165
166
167
168 public long getValue() {
169 return value;
170 }
171
172 @Override
173 public String toString() {
174 return getOpcode().name() + ", " + value;
175 }
176 }
177
178
179
180
181 public static final class PushDoubleTuple extends Tuple {
182 private static final long serialVersionUID = 1L;
183 private final double value;
184
185 PushDoubleTuple(double value) {
186 super(Opcode.PUSH_DOUBLE);
187 this.value = value;
188 }
189
190
191
192
193
194
195 public double getValue() {
196 return value;
197 }
198
199 @Override
200 public String toString() {
201 return getOpcode().name() + ", " + value;
202 }
203 }
204
205
206
207
208 public static final class PushStringTuple extends Tuple {
209 private static final long serialVersionUID = 1L;
210 private final String value;
211
212 PushStringTuple(String value) {
213 super(Opcode.PUSH_STRING);
214 this.value = value;
215 }
216
217
218
219
220
221
222 public String getValue() {
223 return value;
224 }
225
226 @Override
227 public String toString() {
228 return getOpcode().name() + stringArgument(value);
229 }
230 }
231
232
233
234
235 public static class CountTuple extends Tuple {
236 private static final long serialVersionUID = 1L;
237 private final long count;
238
239 CountTuple(Opcode opcode, long count) {
240 super(opcode);
241 this.count = count;
242 }
243
244
245
246
247
248
249 public final long getCount() {
250 return count;
251 }
252
253 @Override
254 public String toString() {
255 return getOpcode().name() + ", " + count;
256 }
257 }
258
259
260
261
262 public static final class CountAndAppendTuple extends CountTuple {
263 private static final long serialVersionUID = 1L;
264 private final boolean append;
265
266 CountAndAppendTuple(Opcode opcode, long count, boolean append) {
267 super(opcode, count);
268 this.append = append;
269 }
270
271
272
273
274
275
276 public boolean isAppend() {
277 return append;
278 }
279
280 @Override
281 public String toString() {
282 return getOpcode().name() + ", " + getCount() + ", " + append;
283 }
284 }
285
286
287
288
289 public static class LongTuple extends Tuple {
290 private static final long serialVersionUID = 1L;
291 private final long value;
292
293 LongTuple(Opcode opcode, long value) {
294 super(opcode);
295 this.value = value;
296 }
297
298
299
300
301
302
303 public final long getValue() {
304 return value;
305 }
306
307 @Override
308 public String toString() {
309 return getOpcode().name() + ", " + value;
310 }
311 }
312
313
314
315
316 public static final class InputFieldTuple extends LongTuple {
317 private static final long serialVersionUID = 1L;
318
319 InputFieldTuple(long fieldIndex) {
320 super(Opcode.GET_INPUT_FIELD_CONST, fieldIndex);
321 }
322
323
324
325
326
327
328 public long getFieldIndex() {
329 return getValue();
330 }
331 }
332
333
334
335
336 public static class AddressTuple extends Tuple {
337 private static final long serialVersionUID = 1L;
338 private Address address;
339
340 AddressTuple(Opcode opcode, Address address) {
341 super(opcode);
342 this.address = address;
343 }
344
345 @Override
346 public Address getAddress() {
347 return address;
348 }
349
350 void setAddress(Address address) {
351 this.address = address;
352 }
353
354 @Override
355 public String toString() {
356 return getOpcode().name() + ", " + address;
357 }
358 }
359
360
361
362
363 public static class VariableTuple extends Tuple {
364 private static final long serialVersionUID = 1L;
365 private final long variableOffset;
366 private final boolean global;
367
368 VariableTuple(Opcode opcode, long variableOffset, boolean global) {
369 super(opcode);
370 this.variableOffset = variableOffset;
371 this.global = global;
372 }
373
374
375
376
377
378
379 public final long getVariableOffset() {
380 return variableOffset;
381 }
382
383
384
385
386
387
388 public final boolean isGlobal() {
389 return global;
390 }
391
392 @Override
393 public String toString() {
394 return getOpcode().name() + ", " + variableOffset + ", " + global;
395 }
396 }
397
398
399
400
401 public static final class CompoundAssignTuple extends VariableTuple {
402 private static final long serialVersionUID = 1L;
403
404 CompoundAssignTuple(Opcode opcode, long variableOffset, boolean global) {
405 super(opcode, variableOffset, global);
406 }
407 }
408
409
410
411
412 public static final class CompoundAssignArrayTuple extends VariableTuple {
413 private static final long serialVersionUID = 1L;
414
415 CompoundAssignArrayTuple(Opcode opcode, long variableOffset, boolean global) {
416 super(opcode, variableOffset, global);
417 }
418 }
419
420
421
422
423 public static final class CompoundAssignMapElementTuple extends NoOperandTuple {
424 private static final long serialVersionUID = 1L;
425
426 CompoundAssignMapElementTuple(Opcode opcode) {
427 super(opcode);
428 }
429 }
430
431
432
433
434 public static final class CompoundAssignInputFieldTuple extends NoOperandTuple {
435 private static final long serialVersionUID = 1L;
436
437 CompoundAssignInputFieldTuple(Opcode opcode) {
438 super(opcode);
439 }
440 }
441
442
443
444
445 public static final class DereferenceTuple extends Tuple {
446 private static final long serialVersionUID = 1L;
447 private final long variableOffset;
448 private final boolean array;
449 private final boolean global;
450
451 DereferenceTuple(long variableOffset, boolean array, boolean global) {
452 super(Opcode.DEREFERENCE);
453 this.variableOffset = variableOffset;
454 this.array = array;
455 this.global = global;
456 }
457
458
459
460
461
462
463 public long getVariableOffset() {
464 return variableOffset;
465 }
466
467
468
469
470
471
472 public boolean isArray() {
473 return array;
474 }
475
476
477
478
479
480
481 public boolean isGlobal() {
482 return global;
483 }
484
485 @Override
486 public String toString() {
487 return getOpcode().name() + ", " + variableOffset + ", " + array + ", " + global;
488 }
489 }
490
491
492
493
494 public static final class BooleanTuple extends Tuple {
495 private static final long serialVersionUID = 1L;
496 private final boolean value;
497
498 BooleanTuple(Opcode opcode, boolean value) {
499 super(opcode);
500 this.value = value;
501 }
502
503
504
505
506
507
508 public boolean getValue() {
509 return value;
510 }
511
512 @Override
513 public String toString() {
514 return getOpcode().name() + ", " + value;
515 }
516 }
517
518
519
520
521 public static final class SubstitutionVariableTuple extends VariableTuple {
522 private static final long serialVersionUID = 1L;
523 private final boolean globalSubstitution;
524
525 SubstitutionVariableTuple(Opcode opcode, long variableOffset, boolean global, boolean globalSubstitution) {
526 super(opcode, variableOffset, global);
527 this.globalSubstitution = globalSubstitution;
528 }
529
530
531
532
533
534
535 public boolean isGlobalSubstitution() {
536 return globalSubstitution;
537 }
538
539 @Override
540 public String toString() {
541 return getOpcode().name() + ", " + getVariableOffset() + ", " + isGlobal() + ", " + globalSubstitution;
542 }
543 }
544
545
546
547
548 public static final class RegexTuple extends Tuple {
549 private static final long serialVersionUID = 1L;
550 private final String regex;
551 private final Pattern pattern;
552
553 RegexTuple(String regex, Pattern pattern) {
554 super(Opcode.REGEXP);
555 this.regex = regex;
556 this.pattern = pattern;
557 }
558
559
560
561
562
563
564 public String getRegex() {
565 return regex;
566 }
567
568
569
570
571
572
573 public Pattern getPattern() {
574 return pattern;
575 }
576
577 @Override
578 public String toString() {
579 return getOpcode().name() + stringArgument(regex) + patternArgument(pattern);
580 }
581 }
582
583
584
585
586 public static final class ClassTuple extends Tuple {
587 private static final long serialVersionUID = 1L;
588 private final Class<?> type;
589
590 ClassTuple(Class<?> type) {
591 super(Opcode.CHECK_CLASS);
592 this.type = type;
593 }
594
595
596
597
598
599
600 public Class<?> getType() {
601 return type;
602 }
603
604 @Override
605 public String toString() {
606 return getOpcode().name() + ", " + type;
607 }
608 }
609
610
611
612
613 public static final class FunctionTuple extends Tuple {
614 private static final long serialVersionUID = 1L;
615 private final String functionName;
616 private final long numFormalParams;
617
618 FunctionTuple(String functionName, long numFormalParams) {
619 super(Opcode.FUNCTION);
620 this.functionName = functionName;
621 this.numFormalParams = numFormalParams;
622 }
623
624
625
626
627
628
629 public String getFunctionName() {
630 return functionName;
631 }
632
633
634
635
636
637
638 public long getNumFormalParams() {
639 return numFormalParams;
640 }
641
642 @Override
643 public String toString() {
644 return getOpcode().name() + stringArgument(functionName) + ", " + numFormalParams;
645 }
646 }
647
648
649
650
651 public static final class CallFunctionTuple extends AddressTuple {
652 private static final long serialVersionUID = 1L;
653 private transient Supplier<Address> addressSupplier;
654 private final String functionName;
655 private final long numFormalParams;
656 private final long numActualParams;
657
658 CallFunctionTuple(
659 Supplier<Address> addressSupplier,
660 String functionName,
661 long numFormalParams,
662 long numActualParams) {
663 super(Opcode.CALL_FUNCTION, null);
664 this.addressSupplier = addressSupplier;
665 this.functionName = functionName;
666 this.numFormalParams = numFormalParams;
667 this.numActualParams = numActualParams;
668 }
669
670 @Override
671 public Address getAddress() {
672 Address address = super.getAddress();
673 if (address == null && addressSupplier != null) {
674 address = addressSupplier.get();
675 setAddress(address);
676 addressSupplier = null;
677 }
678 return address;
679 }
680
681 @Override
682 public void touch(List<Tuple> queue) {
683 getAddress();
684 super.touch(queue);
685 }
686
687
688
689
690
691
692 public String getFunctionName() {
693 return functionName;
694 }
695
696
697
698
699
700
701 public long getNumFormalParams() {
702 return numFormalParams;
703 }
704
705
706
707
708
709
710 public long getNumActualParams() {
711 return numActualParams;
712 }
713
714 @Override
715 public String toString() {
716 return getOpcode().name()
717 + ", "
718 + getAddress()
719 + stringArgument(functionName)
720 + ", "
721 + numFormalParams
722 + ", "
723 + numActualParams;
724 }
725 }
726
727
728
729
730 public static final class ExtensionTuple extends Tuple {
731 private static final long serialVersionUID = 1L;
732 private final ExtensionFunction function;
733 private final long argCount;
734 private final boolean initial;
735
736 ExtensionTuple(ExtensionFunction function, long argCount, boolean initial) {
737 super(Opcode.EXTENSION);
738 this.function = function;
739 this.argCount = argCount;
740 this.initial = initial;
741 }
742
743
744
745
746
747
748 public ExtensionFunction getFunction() {
749 return function;
750 }
751
752
753
754
755
756
757 public long getArgCount() {
758 return argCount;
759 }
760
761
762
763
764
765
766 public boolean isInitial() {
767 return initial;
768 }
769
770 @Override
771 public String toString() {
772 return getOpcode().name() + ", " + function.getKeyword() + ", " + argCount + ", " + initial;
773 }
774 }
775 }