View Javadoc
1   package org.metricshub.jawk.intermediate;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2025 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.io.PrintStream;
26  import java.io.Serializable;
27  import java.util.ArrayDeque;
28  import java.util.ArrayList;
29  import java.util.Collections;
30  import java.util.Deque;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.Map;
34  import java.util.Set;
35  import java.util.function.Supplier;
36  import org.metricshub.jawk.ext.ExtensionFunction;
37  
38  /**
39   * <p>
40   * AwkTuples class.
41   * </p>
42   *
43   * @author Danny Daglas
44   */
45  public class AwkTuples implements Serializable {
46  
47  	private static final long serialVersionUID = 2L;
48  
49  	/** Version Manager */
50  	private VersionManager versionManager = new VersionManager();
51  
52  	/** Address manager */
53  	private final AddressManager addressManager = new AddressManager();
54  
55  	// made public to access static members of AwkTuples via Java Reflection
56  
57  	// made public to be accessable via Java Reflection
58  	// (see toOpcodeString() method below)
59  
60  	/**
61  	 * Override add() to populate the line number for each tuple,
62  	 * rather than polluting all the constructors with this assignment.
63  	 */
64  	private java.util.List<Tuple> queue = new ArrayList<Tuple>(100) {
65  		private static final long serialVersionUID = -6334362156408598578L;
66  
67  		@Override
68  		public boolean add(Tuple t) {
69  			t.setLineNumber(linenoStack.peek());
70  			return super.add(t);
71  		}
72  	};
73  
74  	/**
75  	 * <p>
76  	 * toOpcodeString.
77  	 * </p>
78  	 *
79  	 * @param opcode a int
80  	 * @return a {@link java.lang.String} object
81  	 */
82  	public static String toOpcodeString(int opcode) {
83  		return Opcode.fromId(opcode).name();
84  	}
85  
86  	/**
87  	 * <p>
88  	 * pop.
89  	 * </p>
90  	 */
91  	public void pop() {
92  		queue.add(new Tuple(Opcode.POP));
93  	}
94  
95  	/**
96  	 * <p>
97  	 * push.
98  	 * </p>
99  	 *
100 	 * @param o a {@link java.lang.Object} object
101 	 */
102 	public void push(Object o) {
103 		assert (o instanceof String) || (o instanceof Long) || (o instanceof Integer) || (o instanceof Double); // || (o
104 																																																						// instanceof
105 																																																						// Pattern);
106 		if (o instanceof String) {
107 			queue.add(new Tuple(Opcode.PUSH, o.toString()));
108 		} else if (o instanceof Integer) {
109 			queue.add(new Tuple(Opcode.PUSH, (Integer) o));
110 		} else if (o instanceof Long) {
111 			queue.add(new Tuple(Opcode.PUSH, (Long) o));
112 		} else if (o instanceof Double) {
113 			queue.add(new Tuple(Opcode.PUSH, (Double) o));
114 		} else {
115 			assert false : "Invalid type for " + o + ", " + o.getClass();
116 		}
117 	}
118 
119 	/**
120 	 * <p>
121 	 * ifFalse.
122 	 * </p>
123 	 *
124 	 * @param address a {@link org.metricshub.jawk.intermediate.Address} object
125 	 */
126 	public void ifFalse(Address address) {
127 		queue.add(new Tuple(Opcode.IFFALSE, address));
128 	}
129 
130 	/**
131 	 * <p>
132 	 * toNumber.
133 	 * </p>
134 	 */
135 	public void toNumber() {
136 		queue.add(new Tuple(Opcode.TO_NUMBER));
137 	}
138 
139 	/**
140 	 * <p>
141 	 * ifTrue.
142 	 * </p>
143 	 *
144 	 * @param address a {@link org.metricshub.jawk.intermediate.Address} object
145 	 */
146 	public void ifTrue(Address address) {
147 		queue.add(new Tuple(Opcode.IFTRUE, address));
148 	}
149 
150 	/**
151 	 * <p>
152 	 * gotoAddress.
153 	 * </p>
154 	 *
155 	 * @param address a {@link org.metricshub.jawk.intermediate.Address} object
156 	 */
157 	public void gotoAddress(Address address) {
158 		queue.add(new Tuple(Opcode.GOTO, address));
159 	}
160 
161 	/**
162 	 * <p>
163 	 * createAddress.
164 	 * </p>
165 	 *
166 	 * @param label a {@link java.lang.String} object
167 	 * @return a {@link org.metricshub.jawk.intermediate.Address} object
168 	 */
169 	public Address createAddress(String label) {
170 		return addressManager.createAddress(label);
171 	}
172 
173 	/**
174 	 * <p>
175 	 * address.
176 	 * </p>
177 	 *
178 	 * @param address a {@link org.metricshub.jawk.intermediate.Address} object
179 	 * @return a {@link org.metricshub.jawk.intermediate.AwkTuples} object
180 	 */
181 	public AwkTuples address(Address address) {
182 		addressManager.resolveAddress(address, queue.size());
183 		return this;
184 	}
185 
186 	/**
187 	 * <p>
188 	 * nop.
189 	 * </p>
190 	 */
191 	public void nop() {
192 		queue.add(new Tuple(Opcode.NOP));
193 	}
194 
195 	/**
196 	 * <p>
197 	 * print.
198 	 * </p>
199 	 *
200 	 * @param numExprs a int
201 	 */
202 	public void print(int numExprs) {
203 		queue.add(new Tuple(Opcode.PRINT, numExprs));
204 	}
205 
206 	/**
207 	 * <p>
208 	 * printToFile.
209 	 * </p>
210 	 *
211 	 * @param numExprs a int
212 	 * @param append a boolean
213 	 */
214 	public void printToFile(int numExprs, boolean append) {
215 		queue.add(new Tuple(Opcode.PRINT_TO_FILE, numExprs, append));
216 	}
217 
218 	/**
219 	 * <p>
220 	 * printToPipe.
221 	 * </p>
222 	 *
223 	 * @param numExprs a int
224 	 */
225 	public void printToPipe(int numExprs) {
226 		queue.add(new Tuple(Opcode.PRINT_TO_PIPE, numExprs));
227 	}
228 
229 	/**
230 	 * <p>
231 	 * printf.
232 	 * </p>
233 	 *
234 	 * @param numExprs a int
235 	 */
236 	public void printf(int numExprs) {
237 		queue.add(new Tuple(Opcode.PRINTF, numExprs));
238 	}
239 
240 	/**
241 	 * <p>
242 	 * printfToFile.
243 	 * </p>
244 	 *
245 	 * @param numExprs a int
246 	 * @param append a boolean
247 	 */
248 	public void printfToFile(int numExprs, boolean append) {
249 		queue.add(new Tuple(Opcode.PRINTF_TO_FILE, numExprs, append));
250 	}
251 
252 	/**
253 	 * <p>
254 	 * printfToPipe.
255 	 * </p>
256 	 *
257 	 * @param numExprs a int
258 	 */
259 	public void printfToPipe(int numExprs) {
260 		queue.add(new Tuple(Opcode.PRINTF_TO_PIPE, numExprs));
261 	}
262 
263 	/**
264 	 * <p>
265 	 * sprintf.
266 	 * </p>
267 	 *
268 	 * @param numExprs a int
269 	 */
270 	public void sprintf(int numExprs) {
271 		queue.add(new Tuple(Opcode.SPRINTF, numExprs));
272 	}
273 
274 	/**
275 	 * <p>
276 	 * length.
277 	 * </p>
278 	 *
279 	 * @param numExprs a int
280 	 */
281 	public void length(int numExprs) {
282 		queue.add(new Tuple(Opcode.LENGTH, numExprs));
283 	}
284 
285 	/**
286 	 * <p>
287 	 * concat.
288 	 * </p>
289 	 */
290 	public void concat() {
291 		queue.add(new Tuple(Opcode.CONCAT));
292 	}
293 
294 	/**
295 	 * <p>
296 	 * assign.
297 	 * </p>
298 	 *
299 	 * @param offset a int
300 	 * @param isGlobal a boolean
301 	 */
302 	public void assign(int offset, boolean isGlobal) {
303 		queue.add(new Tuple(Opcode.ASSIGN, offset, isGlobal));
304 	}
305 
306 	/**
307 	 * <p>
308 	 * assignArray.
309 	 * </p>
310 	 *
311 	 * @param offset a int
312 	 * @param isGlobal a boolean
313 	 */
314 	public void assignArray(int offset, boolean isGlobal) {
315 		queue.add(new Tuple(Opcode.ASSIGN_ARRAY, offset, isGlobal));
316 	}
317 
318 	/**
319 	 * <p>
320 	 * assignAsInput.
321 	 * </p>
322 	 */
323 	public void assignAsInput() {
324 		queue.add(new Tuple(Opcode.ASSIGN_AS_INPUT));
325 	}
326 
327 	/**
328 	 * Use this only in initialization for simple evaluation
329 	 */
330 	public void setInputForEval() {
331 		queue.add(new Tuple(Opcode.SET_INPUT_FOR_EVAL));
332 	}
333 
334 	/**
335 	 * <p>
336 	 * assignAsInputField.
337 	 * </p>
338 	 */
339 	public void assignAsInputField() {
340 		queue.add(new Tuple(Opcode.ASSIGN_AS_INPUT_FIELD));
341 	}
342 
343 	/**
344 	 * <p>
345 	 * dereference.
346 	 * </p>
347 	 *
348 	 * @param offset a int
349 	 * @param isArray a boolean
350 	 * @param isGlobal a boolean
351 	 */
352 	public void dereference(int offset, boolean isArray, boolean isGlobal) {
353 		queue.add(new Tuple(Opcode.DEREFERENCE, offset, isArray, isGlobal));
354 	}
355 
356 	/**
357 	 * <p>
358 	 * plusEq.
359 	 * </p>
360 	 *
361 	 * @param offset a int
362 	 * @param isGlobal a boolean
363 	 */
364 	public void plusEq(int offset, boolean isGlobal) {
365 		queue.add(new Tuple(Opcode.PLUS_EQ, offset, isGlobal));
366 	}
367 
368 	/**
369 	 * <p>
370 	 * minusEq.
371 	 * </p>
372 	 *
373 	 * @param offset a int
374 	 * @param isGlobal a boolean
375 	 */
376 	public void minusEq(int offset, boolean isGlobal) {
377 		queue.add(new Tuple(Opcode.MINUS_EQ, offset, isGlobal));
378 	}
379 
380 	/**
381 	 * <p>
382 	 * multEq.
383 	 * </p>
384 	 *
385 	 * @param offset a int
386 	 * @param isGlobal a boolean
387 	 */
388 	public void multEq(int offset, boolean isGlobal) {
389 		queue.add(new Tuple(Opcode.MULT_EQ, offset, isGlobal));
390 	}
391 
392 	/**
393 	 * <p>
394 	 * divEq.
395 	 * </p>
396 	 *
397 	 * @param offset a int
398 	 * @param isGlobal a boolean
399 	 */
400 	public void divEq(int offset, boolean isGlobal) {
401 		queue.add(new Tuple(Opcode.DIV_EQ, offset, isGlobal));
402 	}
403 
404 	/**
405 	 * <p>
406 	 * modEq.
407 	 * </p>
408 	 *
409 	 * @param offset a int
410 	 * @param isGlobal a boolean
411 	 */
412 	public void modEq(int offset, boolean isGlobal) {
413 		queue.add(new Tuple(Opcode.MOD_EQ, offset, isGlobal));
414 	}
415 
416 	/**
417 	 * <p>
418 	 * powEq.
419 	 * </p>
420 	 *
421 	 * @param offset a int
422 	 * @param isGlobal a boolean
423 	 */
424 	public void powEq(int offset, boolean isGlobal) {
425 		queue.add(new Tuple(Opcode.POW_EQ, offset, isGlobal));
426 	}
427 
428 	/**
429 	 * <p>
430 	 * plusEqArray.
431 	 * </p>
432 	 *
433 	 * @param offset a int
434 	 * @param isGlobal a boolean
435 	 */
436 	public void plusEqArray(int offset, boolean isGlobal) {
437 		queue.add(new Tuple(Opcode.PLUS_EQ_ARRAY, offset, isGlobal));
438 	}
439 
440 	/**
441 	 * <p>
442 	 * minusEqArray.
443 	 * </p>
444 	 *
445 	 * @param offset a int
446 	 * @param isGlobal a boolean
447 	 */
448 	public void minusEqArray(int offset, boolean isGlobal) {
449 		queue.add(new Tuple(Opcode.MINUS_EQ_ARRAY, offset, isGlobal));
450 	}
451 
452 	/**
453 	 * <p>
454 	 * multEqArray.
455 	 * </p>
456 	 *
457 	 * @param offset a int
458 	 * @param isGlobal a boolean
459 	 */
460 	public void multEqArray(int offset, boolean isGlobal) {
461 		queue.add(new Tuple(Opcode.MULT_EQ_ARRAY, offset, isGlobal));
462 	}
463 
464 	/**
465 	 * <p>
466 	 * divEqArray.
467 	 * </p>
468 	 *
469 	 * @param offset a int
470 	 * @param isGlobal a boolean
471 	 */
472 	public void divEqArray(int offset, boolean isGlobal) {
473 		queue.add(new Tuple(Opcode.DIV_EQ_ARRAY, offset, isGlobal));
474 	}
475 
476 	/**
477 	 * <p>
478 	 * modEqArray.
479 	 * </p>
480 	 *
481 	 * @param offset a int
482 	 * @param isGlobal a boolean
483 	 */
484 	public void modEqArray(int offset, boolean isGlobal) {
485 		queue.add(new Tuple(Opcode.MOD_EQ_ARRAY, offset, isGlobal));
486 	}
487 
488 	/**
489 	 * <p>
490 	 * powEqArray.
491 	 * </p>
492 	 *
493 	 * @param offset a int
494 	 * @param isGlobal a boolean
495 	 */
496 	public void powEqArray(int offset, boolean isGlobal) {
497 		queue.add(new Tuple(Opcode.POW_EQ_ARRAY, offset, isGlobal));
498 	}
499 
500 	/**
501 	 * <p>
502 	 * plusEqInputField.
503 	 * </p>
504 	 */
505 	public void plusEqInputField() {
506 		queue.add(new Tuple(Opcode.PLUS_EQ_INPUT_FIELD));
507 	}
508 
509 	/**
510 	 * <p>
511 	 * minusEqInputField.
512 	 * </p>
513 	 */
514 	public void minusEqInputField() {
515 		queue.add(new Tuple(Opcode.MINUS_EQ_INPUT_FIELD));
516 	}
517 
518 	/**
519 	 * <p>
520 	 * multEqInputField.
521 	 * </p>
522 	 */
523 	public void multEqInputField() {
524 		queue.add(new Tuple(Opcode.MULT_EQ_INPUT_FIELD));
525 	}
526 
527 	/**
528 	 * <p>
529 	 * divEqInputField.
530 	 * </p>
531 	 */
532 	public void divEqInputField() {
533 		queue.add(new Tuple(Opcode.DIV_EQ_INPUT_FIELD));
534 	}
535 
536 	/**
537 	 * <p>
538 	 * modEqInputField.
539 	 * </p>
540 	 */
541 	public void modEqInputField() {
542 		queue.add(new Tuple(Opcode.MOD_EQ_INPUT_FIELD));
543 	}
544 
545 	/**
546 	 * <p>
547 	 * powEqInputField.
548 	 * </p>
549 	 */
550 	public void powEqInputField() {
551 		queue.add(new Tuple(Opcode.POW_EQ_INPUT_FIELD));
552 	}
553 
554 	/**
555 	 * <p>
556 	 * srand.
557 	 * </p>
558 	 *
559 	 * @param num a int
560 	 */
561 	public void srand(int num) {
562 		queue.add(new Tuple(Opcode.SRAND, num));
563 	}
564 
565 	/**
566 	 * <p>
567 	 * rand.
568 	 * </p>
569 	 */
570 	public void rand() {
571 		queue.add(new Tuple(Opcode.RAND));
572 	}
573 
574 	/**
575 	 * <p>
576 	 * intFunc.
577 	 * </p>
578 	 */
579 	public void intFunc() {
580 		queue.add(new Tuple(Opcode.INTFUNC));
581 	}
582 
583 	/**
584 	 * <p>
585 	 * sqrt.
586 	 * </p>
587 	 */
588 	public void sqrt() {
589 		queue.add(new Tuple(Opcode.SQRT));
590 	}
591 
592 	/**
593 	 * <p>
594 	 * log.
595 	 * </p>
596 	 */
597 	public void log() {
598 		queue.add(new Tuple(Opcode.LOG));
599 	}
600 
601 	/**
602 	 * <p>
603 	 * exp.
604 	 * </p>
605 	 */
606 	public void exp() {
607 		queue.add(new Tuple(Opcode.EXP));
608 	}
609 
610 	/**
611 	 * <p>
612 	 * sin.
613 	 * </p>
614 	 */
615 	public void sin() {
616 		queue.add(new Tuple(Opcode.SIN));
617 	}
618 
619 	/**
620 	 * <p>
621 	 * cos.
622 	 * </p>
623 	 */
624 	public void cos() {
625 		queue.add(new Tuple(Opcode.COS));
626 	}
627 
628 	/**
629 	 * <p>
630 	 * atan2.
631 	 * </p>
632 	 */
633 	public void atan2() {
634 		queue.add(new Tuple(Opcode.ATAN2));
635 	}
636 
637 	/**
638 	 * <p>
639 	 * match.
640 	 * </p>
641 	 */
642 	public void match() {
643 		queue.add(new Tuple(Opcode.MATCH));
644 	}
645 
646 	/**
647 	 * <p>
648 	 * index.
649 	 * </p>
650 	 */
651 	public void index() {
652 		queue.add(new Tuple(Opcode.INDEX));
653 	}
654 
655 	/**
656 	 * <p>
657 	 * subForDollar0.
658 	 * </p>
659 	 *
660 	 * @param isGsub a boolean
661 	 */
662 	public void subForDollar0(boolean isGsub) {
663 		queue.add(new Tuple(Opcode.SUB_FOR_DOLLAR_0, isGsub));
664 	}
665 
666 	/**
667 	 * <p>
668 	 * subForDollarReference.
669 	 * </p>
670 	 *
671 	 * @param isGsub a boolean
672 	 */
673 	public void subForDollarReference(boolean isGsub) {
674 		queue.add(new Tuple(Opcode.SUB_FOR_DOLLAR_REFERENCE, isGsub));
675 	}
676 
677 	/**
678 	 * <p>
679 	 * subForVariable.
680 	 * </p>
681 	 *
682 	 * @param offset a int
683 	 * @param isGlobal a boolean
684 	 * @param isGsub a boolean
685 	 */
686 	public void subForVariable(int offset, boolean isGlobal, boolean isGsub) {
687 		queue.add(new Tuple(Opcode.SUB_FOR_VARIABLE, offset, isGlobal, isGsub));
688 	}
689 
690 	/**
691 	 * <p>
692 	 * subForArrayReference.
693 	 * </p>
694 	 *
695 	 * @param offset a int
696 	 * @param isGlobal a boolean
697 	 * @param isGsub a boolean
698 	 */
699 	public void subForArrayReference(int offset, boolean isGlobal, boolean isGsub) {
700 		queue.add(new Tuple(Opcode.SUB_FOR_ARRAY_REFERENCE, offset, isGlobal, isGsub));
701 	}
702 
703 	/**
704 	 * <p>
705 	 * split.
706 	 * </p>
707 	 *
708 	 * @param numargs a int
709 	 */
710 	public void split(int numargs) {
711 		queue.add(new Tuple(Opcode.SPLIT, numargs));
712 	}
713 
714 	/**
715 	 * <p>
716 	 * substr.
717 	 * </p>
718 	 *
719 	 * @param numargs a int
720 	 */
721 	public void substr(int numargs) {
722 		queue.add(new Tuple(Opcode.SUBSTR, numargs));
723 	}
724 
725 	/**
726 	 * <p>
727 	 * tolower.
728 	 * </p>
729 	 */
730 	public void tolower() {
731 		queue.add(new Tuple(Opcode.TOLOWER));
732 	}
733 
734 	/**
735 	 * <p>
736 	 * toupper.
737 	 * </p>
738 	 */
739 	public void toupper() {
740 		queue.add(new Tuple(Opcode.TOUPPER));
741 	}
742 
743 	/**
744 	 * <p>
745 	 * system.
746 	 * </p>
747 	 */
748 	public void system() {
749 		queue.add(new Tuple(Opcode.SYSTEM));
750 	}
751 
752 	/**
753 	 * <p>
754 	 * exec.
755 	 * </p>
756 	 */
757 	public void exec() {
758 		queue.add(new Tuple(Opcode.EXEC));
759 	}
760 
761 	/**
762 	 * <p>
763 	 * swap.
764 	 * </p>
765 	 */
766 	public void swap() {
767 		queue.add(new Tuple(Opcode.SWAP));
768 	}
769 
770 	/**
771 	 * <p>
772 	 * add.
773 	 * </p>
774 	 */
775 	public void add() {
776 		queue.add(new Tuple(Opcode.ADD));
777 	}
778 
779 	/**
780 	 * <p>
781 	 * subtract.
782 	 * </p>
783 	 */
784 	public void subtract() {
785 		queue.add(new Tuple(Opcode.SUBTRACT));
786 	}
787 
788 	/**
789 	 * <p>
790 	 * multiply.
791 	 * </p>
792 	 */
793 	public void multiply() {
794 		queue.add(new Tuple(Opcode.MULTIPLY));
795 	}
796 
797 	/**
798 	 * <p>
799 	 * divide.
800 	 * </p>
801 	 */
802 	public void divide() {
803 		queue.add(new Tuple(Opcode.DIVIDE));
804 	}
805 
806 	/**
807 	 * <p>
808 	 * mod.
809 	 * </p>
810 	 */
811 	public void mod() {
812 		queue.add(new Tuple(Opcode.MOD));
813 	}
814 
815 	/**
816 	 * <p>
817 	 * pow.
818 	 * </p>
819 	 */
820 	public void pow() {
821 		queue.add(new Tuple(Opcode.POW));
822 	}
823 
824 	/**
825 	 * <p>
826 	 * inc.
827 	 * </p>
828 	 *
829 	 * @param offset a int
830 	 * @param isGlobal a boolean
831 	 */
832 	public void inc(int offset, boolean isGlobal) {
833 		queue.add(new Tuple(Opcode.INC, offset, isGlobal));
834 	}
835 
836 	/**
837 	 * <p>
838 	 * dec.
839 	 * </p>
840 	 *
841 	 * @param offset a int
842 	 * @param isGlobal a boolean
843 	 */
844 	public void dec(int offset, boolean isGlobal) {
845 		queue.add(new Tuple(Opcode.DEC, offset, isGlobal));
846 	}
847 
848 	/**
849 	 * <p>
850 	 * postInc.
851 	 * </p>
852 	 *
853 	 * @param offset a int
854 	 * @param isGlobal a boolean
855 	 */
856 	public void postInc(int offset, boolean isGlobal) {
857 		queue.add(new Tuple(Opcode.POSTINC, offset, isGlobal));
858 	}
859 
860 	/**
861 	 * <p>
862 	 * postDec.
863 	 * </p>
864 	 *
865 	 * @param offset a int
866 	 * @param isGlobal a boolean
867 	 */
868 	public void postDec(int offset, boolean isGlobal) {
869 		queue.add(new Tuple(Opcode.POSTDEC, offset, isGlobal));
870 	}
871 
872 	/**
873 	 * <p>
874 	 * incArrayRef.
875 	 * </p>
876 	 *
877 	 * @param offset a int
878 	 * @param isGlobal a boolean
879 	 */
880 	public void incArrayRef(int offset, boolean isGlobal) {
881 		queue.add(new Tuple(Opcode.INC_ARRAY_REF, offset, isGlobal));
882 	}
883 
884 	/**
885 	 * <p>
886 	 * decArrayRef.
887 	 * </p>
888 	 *
889 	 * @param offset a int
890 	 * @param isGlobal a boolean
891 	 */
892 	public void decArrayRef(int offset, boolean isGlobal) {
893 		queue.add(new Tuple(Opcode.DEC_ARRAY_REF, offset, isGlobal));
894 	}
895 
896 	/**
897 	 * <p>
898 	 * incDollarRef.
899 	 * </p>
900 	 */
901 	public void incDollarRef() {
902 		queue.add(new Tuple(Opcode.INC_DOLLAR_REF));
903 	}
904 
905 	/**
906 	 * <p>
907 	 * decDollarRef.
908 	 * </p>
909 	 */
910 	public void decDollarRef() {
911 		queue.add(new Tuple(Opcode.DEC_DOLLAR_REF));
912 	}
913 
914 	/**
915 	 * <p>
916 	 * dup.
917 	 * </p>
918 	 */
919 	public void dup() {
920 		queue.add(new Tuple(Opcode.DUP));
921 	}
922 
923 	/**
924 	 * <p>
925 	 * not.
926 	 * </p>
927 	 */
928 	public void not() {
929 		queue.add(new Tuple(Opcode.NOT));
930 	}
931 
932 	/**
933 	 * <p>
934 	 * negate.
935 	 * </p>
936 	 */
937 	public void negate() {
938 		queue.add(new Tuple(Opcode.NEGATE));
939 	}
940 
941 	/**
942 	 * <p>
943 	 * unary plus.
944 	 * </p>
945 	 */
946 	public void unaryPlus() {
947 		queue.add(new Tuple(Opcode.UNARY_PLUS));
948 	}
949 
950 	/**
951 	 * <p>
952 	 * cmpEq.
953 	 * </p>
954 	 */
955 	public void cmpEq() {
956 		queue.add(new Tuple(Opcode.CMP_EQ));
957 	}
958 
959 	/**
960 	 * <p>
961 	 * cmpLt.
962 	 * </p>
963 	 */
964 	public void cmpLt() {
965 		queue.add(new Tuple(Opcode.CMP_LT));
966 	}
967 
968 	/**
969 	 * <p>
970 	 * cmpGt.
971 	 * </p>
972 	 */
973 	public void cmpGt() {
974 		queue.add(new Tuple(Opcode.CMP_GT));
975 	}
976 
977 	/**
978 	 * <p>
979 	 * matches.
980 	 * </p>
981 	 */
982 	public void matches() {
983 		queue.add(new Tuple(Opcode.MATCHES));
984 	}
985 
986 	/**
987 	 * <p>
988 	 * dereferenceArray.
989 	 * </p>
990 	 */
991 	public void dereferenceArray() {
992 		queue.add(new Tuple(Opcode.DEREF_ARRAY));
993 	}
994 
995 	/**
996 	 * <p>
997 	 * key list.
998 	 * </p>
999 	 */
1000 	public void keylist() {
1001 		queue.add(new Tuple(Opcode.KEYLIST));
1002 	}
1003 
1004 	/**
1005 	 * <p>
1006 	 * isEmptyList.
1007 	 * </p>
1008 	 *
1009 	 * @param address a {@link org.metricshub.jawk.intermediate.Address} object
1010 	 */
1011 	public void isEmptyList(Address address) {
1012 		queue.add(new Tuple(Opcode.IS_EMPTY_KEYLIST, address));
1013 	}
1014 
1015 	/**
1016 	 * <p>
1017 	 * getFirstAndRemoveFromList.
1018 	 * </p>
1019 	 */
1020 	public void getFirstAndRemoveFromList() {
1021 		queue.add(new Tuple(Opcode.GET_FIRST_AND_REMOVE_FROM_KEYLIST));
1022 	}
1023 
1024 	/**
1025 	 * <p>
1026 	 * checkClass.
1027 	 * </p>
1028 	 *
1029 	 * @param cls a {@link java.lang.Class} object
1030 	 * @return a boolean
1031 	 */
1032 	public boolean checkClass(Class<?> cls) {
1033 		queue.add(new Tuple(Opcode.CHECK_CLASS, cls));
1034 		return true;
1035 	}
1036 
1037 	/**
1038 	 * <p>
1039 	 * getInputField.
1040 	 * </p>
1041 	 */
1042 	public void getInputField() {
1043 		queue.add(new Tuple(Opcode.GET_INPUT_FIELD));
1044 	}
1045 
1046 	/**
1047 	 * <p>
1048 	 * consumeInput.
1049 	 * </p>
1050 	 *
1051 	 * @param address a {@link org.metricshub.jawk.intermediate.Address} object
1052 	 */
1053 	public void consumeInput(Address address) {
1054 		queue.add(new Tuple(Opcode.CONSUME_INPUT, address));
1055 	}
1056 
1057 	/**
1058 	 * <p>
1059 	 * getlineInput.
1060 	 * </p>
1061 	 */
1062 	public void getlineInput() {
1063 		queue.add(new Tuple(Opcode.GETLINE_INPUT));
1064 	}
1065 
1066 	/**
1067 	 * <p>
1068 	 * useAsFileInput.
1069 	 * </p>
1070 	 */
1071 	public void useAsFileInput() {
1072 		queue.add(new Tuple(Opcode.USE_AS_FILE_INPUT));
1073 	}
1074 
1075 	/**
1076 	 * <p>
1077 	 * useAsCommandInput.
1078 	 * </p>
1079 	 */
1080 	public void useAsCommandInput() {
1081 		queue.add(new Tuple(Opcode.USE_AS_COMMAND_INPUT));
1082 	}
1083 
1084 	/**
1085 	 * <p>
1086 	 * nfOffset.
1087 	 * </p>
1088 	 *
1089 	 * @param offset a int
1090 	 */
1091 	public void nfOffset(int offset) {
1092 		queue.add(new Tuple(Opcode.NF_OFFSET, offset));
1093 	}
1094 
1095 	/**
1096 	 * <p>
1097 	 * nrOffset.
1098 	 * </p>
1099 	 *
1100 	 * @param offset a int
1101 	 */
1102 	public void nrOffset(int offset) {
1103 		queue.add(new Tuple(Opcode.NR_OFFSET, offset));
1104 	}
1105 
1106 	/**
1107 	 * <p>
1108 	 * fnrOffset.
1109 	 * </p>
1110 	 *
1111 	 * @param offset a int
1112 	 */
1113 	public void fnrOffset(int offset) {
1114 		queue.add(new Tuple(Opcode.FNR_OFFSET, offset));
1115 	}
1116 
1117 	/**
1118 	 * <p>
1119 	 * fsOffset.
1120 	 * </p>
1121 	 *
1122 	 * @param offset a int
1123 	 */
1124 	public void fsOffset(int offset) {
1125 		queue.add(new Tuple(Opcode.FS_OFFSET, offset));
1126 	}
1127 
1128 	/**
1129 	 * <p>
1130 	 * rsOffset.
1131 	 * </p>
1132 	 *
1133 	 * @param offset a int
1134 	 */
1135 	public void rsOffset(int offset) {
1136 		queue.add(new Tuple(Opcode.RS_OFFSET, offset));
1137 	}
1138 
1139 	/**
1140 	 * <p>
1141 	 * ofsOffset.
1142 	 * </p>
1143 	 *
1144 	 * @param offset a int
1145 	 */
1146 	public void ofsOffset(int offset) {
1147 		queue.add(new Tuple(Opcode.OFS_OFFSET, offset));
1148 	}
1149 
1150 	/**
1151 	 * <p>
1152 	 * orsOffset.
1153 	 * </p>
1154 	 *
1155 	 * @param offset a int
1156 	 */
1157 	public void orsOffset(int offset) {
1158 		queue.add(new Tuple(Opcode.ORS_OFFSET, offset));
1159 	}
1160 
1161 	/**
1162 	 * <p>
1163 	 * rstartOffset.
1164 	 * </p>
1165 	 *
1166 	 * @param offset a int
1167 	 */
1168 	public void rstartOffset(int offset) {
1169 		queue.add(new Tuple(Opcode.RSTART_OFFSET, offset));
1170 	}
1171 
1172 	/**
1173 	 * <p>
1174 	 * rlengthOffset.
1175 	 * </p>
1176 	 *
1177 	 * @param offset a int
1178 	 */
1179 	public void rlengthOffset(int offset) {
1180 		queue.add(new Tuple(Opcode.RLENGTH_OFFSET, offset));
1181 	}
1182 
1183 	/**
1184 	 * <p>
1185 	 * filenameOffset.
1186 	 * </p>
1187 	 *
1188 	 * @param offset a int
1189 	 */
1190 	public void filenameOffset(int offset) {
1191 		queue.add(new Tuple(Opcode.FILENAME_OFFSET, offset));
1192 	}
1193 
1194 	/**
1195 	 * <p>
1196 	 * subsepOffset.
1197 	 * </p>
1198 	 *
1199 	 * @param offset a int
1200 	 */
1201 	public void subsepOffset(int offset) {
1202 		queue.add(new Tuple(Opcode.SUBSEP_OFFSET, offset));
1203 	}
1204 
1205 	/**
1206 	 * <p>
1207 	 * convfmtOffset.
1208 	 * </p>
1209 	 *
1210 	 * @param offset a int
1211 	 */
1212 	public void convfmtOffset(int offset) {
1213 		queue.add(new Tuple(Opcode.CONVFMT_OFFSET, offset));
1214 	}
1215 
1216 	/**
1217 	 * <p>
1218 	 * ofmtOffset.
1219 	 * </p>
1220 	 *
1221 	 * @param offset a int
1222 	 */
1223 	public void ofmtOffset(int offset) {
1224 		queue.add(new Tuple(Opcode.OFMT_OFFSET, offset));
1225 	}
1226 
1227 	/**
1228 	 * <p>
1229 	 * environOffset.
1230 	 * </p>
1231 	 *
1232 	 * @param offset a int
1233 	 */
1234 	public void environOffset(int offset) {
1235 		queue.add(new Tuple(Opcode.ENVIRON_OFFSET, offset));
1236 	}
1237 
1238 	/**
1239 	 * <p>
1240 	 * argcOffset.
1241 	 * </p>
1242 	 *
1243 	 * @param offset a int
1244 	 */
1245 	public void argcOffset(int offset) {
1246 		queue.add(new Tuple(Opcode.ARGC_OFFSET, offset));
1247 	}
1248 
1249 	/**
1250 	 * <p>
1251 	 * argvOffset.
1252 	 * </p>
1253 	 *
1254 	 * @param offset a int
1255 	 */
1256 	public void argvOffset(int offset) {
1257 		queue.add(new Tuple(Opcode.ARGV_OFFSET, offset));
1258 	}
1259 
1260 	/**
1261 	 * <p>
1262 	 * applyRS.
1263 	 * </p>
1264 	 */
1265 	public void applyRS() {
1266 		queue.add(new Tuple(Opcode.APPLY_RS));
1267 	}
1268 
1269 	/**
1270 	 * <p>
1271 	 * function.
1272 	 * </p>
1273 	 *
1274 	 * @param funcName a {@link java.lang.String} object
1275 	 * @param numFormalParams a int
1276 	 */
1277 	public void function(String funcName, int numFormalParams) {
1278 		queue.add(new Tuple(Opcode.FUNCTION, funcName, numFormalParams));
1279 	}
1280 
1281 	// public void callFunction(Address addr, String funcName, int numFormalParams, int numActualParams) {
1282 	// queue.add(new Tuple(Opcode.CALL_FUNCTION, addr, funcName, numFormalParams, numActualParams)); }
1283 
1284 	/**
1285 	 * <p>
1286 	 * callFunction.
1287 	 * </p>
1288 	 *
1289 	 * @param addressSupplier supplier resolving the function's entry point
1290 	 * @param funcName a {@link java.lang.String} object
1291 	 * @param numFormalParams a int
1292 	 * @param numActualParams a int
1293 	 */
1294 	public void callFunction(
1295 			Supplier<Address> addressSupplier,
1296 			String funcName,
1297 			int numFormalParams,
1298 			int numActualParams) {
1299 		queue.add(new Tuple(Opcode.CALL_FUNCTION, addressSupplier, funcName, numFormalParams, numActualParams));
1300 	}
1301 
1302 	/**
1303 	 * <p>
1304 	 * setReturnResult.
1305 	 * </p>
1306 	 */
1307 	public void setReturnResult() {
1308 		queue.add(new Tuple(Opcode.SET_RETURN_RESULT));
1309 	}
1310 
1311 	/**
1312 	 * <p>
1313 	 * returnFromFunction.
1314 	 * </p>
1315 	 */
1316 	public void returnFromFunction() {
1317 		queue.add(new Tuple(Opcode.RETURN_FROM_FUNCTION));
1318 	}
1319 
1320 	/**
1321 	 * <p>
1322 	 * setNumGlobals.
1323 	 * </p>
1324 	 *
1325 	 * @param numGlobals a int
1326 	 */
1327 	public void setNumGlobals(int numGlobals) {
1328 		queue.add(new Tuple(Opcode.SET_NUM_GLOBALS, numGlobals));
1329 	}
1330 
1331 	/**
1332 	 * <p>
1333 	 * close.
1334 	 * </p>
1335 	 */
1336 	public void close() {
1337 		queue.add(new Tuple(Opcode.CLOSE));
1338 	}
1339 
1340 	/**
1341 	 * <p>
1342 	 * applySubsep.
1343 	 * </p>
1344 	 *
1345 	 * @param count a int
1346 	 */
1347 	public void applySubsep(int count) {
1348 		queue.add(new Tuple(Opcode.APPLY_SUBSEP, count));
1349 	}
1350 
1351 	/**
1352 	 * <p>
1353 	 * deleteArrayElement.
1354 	 * </p>
1355 	 *
1356 	 * @param offset a int
1357 	 * @param isGlobal a boolean
1358 	 */
1359 	public void deleteArrayElement(int offset, boolean isGlobal) {
1360 		queue.add(new Tuple(Opcode.DELETE_ARRAY_ELEMENT, offset, isGlobal));
1361 	}
1362 
1363 	/**
1364 	 * <p>
1365 	 * deleteArray.
1366 	 * </p>
1367 	 *
1368 	 * @param offset a int
1369 	 * @param isGlobal a boolean
1370 	 */
1371 	public void deleteArray(int offset, boolean isGlobal) {
1372 		queue.add(new Tuple(Opcode.DELETE_ARRAY, offset, isGlobal));
1373 	}
1374 
1375 	/**
1376 	 * <p>
1377 	 * setExitAddress.
1378 	 * </p>
1379 	 *
1380 	 * @param addr a {@link org.metricshub.jawk.intermediate.Address} object
1381 	 */
1382 	public void setExitAddress(Address addr) {
1383 		queue.add(new Tuple(Opcode.SET_EXIT_ADDRESS, addr));
1384 	}
1385 
1386 	/**
1387 	 * <p>
1388 	 * setWithinEndBlocks.
1389 	 * </p>
1390 	 *
1391 	 * @param b a boolean
1392 	 */
1393 	public void setWithinEndBlocks(boolean b) {
1394 		queue.add(new Tuple(Opcode.SET_WITHIN_END_BLOCKS, b));
1395 	}
1396 
1397 	/**
1398 	 * <p>
1399 	 * exitWithCode.
1400 	 * </p>
1401 	 */
1402 	public void exitWithCode() {
1403 		queue.add(new Tuple(Opcode.EXIT_WITH_CODE));
1404 	}
1405 
1406 	/**
1407 	 * <p>
1408 	 * exitWithCode.
1409 	 * </p>
1410 	 */
1411 	public void exitWithoutCode() {
1412 		queue.add(new Tuple(Opcode.EXIT_WITHOUT_CODE));
1413 	}
1414 
1415 	/**
1416 	 * <p>
1417 	 * regexp.
1418 	 * </p>
1419 	 *
1420 	 * @param regexpStr a {@link java.lang.String} object
1421 	 */
1422 	public void regexp(String regexpStr) {
1423 		queue.add(new Tuple(Opcode.REGEXP, regexpStr));
1424 	}
1425 
1426 	/**
1427 	 * <p>
1428 	 * regexpPair.
1429 	 * </p>
1430 	 */
1431 	public void conditionPair() {
1432 		queue.add(new Tuple(Opcode.CONDITION_PAIR));
1433 	}
1434 
1435 	/**
1436 	 * <p>
1437 	 * isIn.
1438 	 * </p>
1439 	 */
1440 	public void isIn() {
1441 		queue.add(new Tuple(Opcode.IS_IN));
1442 	}
1443 
1444 	/**
1445 	 * Emits a tuple that pushes the current script context onto the stack.
1446 	 */
1447 	public void scriptThis() {
1448 		queue.add(new Tuple(Opcode.THIS));
1449 	}
1450 
1451 	/**
1452 	 * Emits an extension invocation tuple.
1453 	 *
1454 	 * @param function metadata describing the extension method to invoke
1455 	 * @param paramCount number of arguments supplied for the call
1456 	 * @param isInitial {@code true} when this tuple opens an extension call sequence
1457 	 */
1458 	public void extension(ExtensionFunction function, int paramCount, boolean isInitial) {
1459 		queue.add(new Tuple(Opcode.EXTENSION, function, paramCount, isInitial));
1460 	}
1461 
1462 	/**
1463 	 * Dumps the queued tuples to the provided {@link PrintStream}.
1464 	 *
1465 	 * @param ps destination stream for the tuple listing
1466 	 */
1467 	public void dump(PrintStream ps) {
1468 		ps.println("(" + versionManager + ")");
1469 		ps.println();
1470 		for (int i = 0; i < queue.size(); i++) {
1471 			Address address = addressManager.getAddress(i);
1472 			if (address == null) {
1473 				ps.println(i + " : " + queue.get(i));
1474 			} else {
1475 				ps.println(i + " : [" + address + "] : " + queue.get(i));
1476 			}
1477 		}
1478 	}
1479 
1480 	/**
1481 	 * <p>
1482 	 * top.
1483 	 * </p>
1484 	 *
1485 	 * @return a {@link org.metricshub.jawk.intermediate.PositionTracker} object
1486 	 */
1487 	public PositionTracker top() {
1488 		return new PositionTracker(queue);
1489 	}
1490 
1491 	/**
1492 	 * Executed after all tuples are entered in the queue.
1493 	 * Its main functions are:
1494 	 * <ul>
1495 	 * <li>Assign queue.next to the next element in the queue.
1496 	 * <li>Calls touch(...) per Tuple so that addresses can be normalized/assigned/allocated
1497 	 * properly.
1498 	 * </ul>
1499 	 */
1500 	public void postProcess() {
1501 		assert queue.isEmpty() || !queue.get(0).hasNext() : "postProcess() already executed";
1502 		// allocate nexts
1503 		for (int i = 0; i < queue.size() - 1; i++) {
1504 			queue.get(i).setNext(queue.get(i + 1));
1505 		}
1506 		// touch per element
1507 		for (Tuple tuple : queue) {
1508 			tuple.touch(queue);
1509 		}
1510 	}
1511 
1512 	/** Map of global variables offsets */
1513 	private Map<String, Integer> globalVarOffsetMap = new HashMap<String, Integer>();
1514 
1515 	/** Map of global arrays */
1516 	private Map<String, Boolean> globalVarAarrayMap = new HashMap<String, Boolean>();
1517 
1518 	/** List of user function names */
1519 	private Set<String> functionNames = null;
1520 
1521 	/**
1522 	 * Accept a {variable_name -&gt; offset} mapping such that global variables can be
1523 	 * assigned while processing name=value and filename command-line arguments.
1524 	 *
1525 	 * @param varname Name of the global variable
1526 	 * @param offset What offset to use for the variable
1527 	 * @param isArray Whether the variable is actually an array
1528 	 */
1529 	public void addGlobalVariableNameToOffsetMapping(String varname, int offset, boolean isArray) {
1530 		if (globalVarOffsetMap.get(varname) != null) {
1531 			assert globalVarAarrayMap.get(varname) != null;
1532 			return;
1533 		}
1534 		globalVarOffsetMap.put(varname, offset);
1535 		globalVarAarrayMap.put(varname, isArray);
1536 	}
1537 
1538 	/**
1539 	 * Accept a set of function names from the parser. This is
1540 	 * useful for invalidating name=value assignments from the
1541 	 * command line parameters, either via -v arguments or
1542 	 * passed into ARGV.
1543 	 *
1544 	 * @param names A set of function name strings.
1545 	 */
1546 	public void setFunctionNameSet(Set<String> names) {
1547 		// setFunctionNameSet is called with a keySet from
1548 		// a HashMap as a parameter, which is Opcode.NOT
1549 		// Serializable. Creating a new HashSet around
1550 		// the parameter resolves the issue.
1551 		// Otherwise, attempting to serialize this
1552 		// object results in a NotSerializableEexception
1553 		// being thrown because of functionNames field
1554 		// being a keyset from a HashMap.
1555 		this.functionNames = new HashSet<String>(names);
1556 	}
1557 
1558 	/**
1559 	 * <p>
1560 	 * getGlobalVariableOffsetMap.
1561 	 * </p>
1562 	 *
1563 	 * @return a {@link java.util.Map} object
1564 	 */
1565 	public Map<String, Integer> getGlobalVariableOffsetMap() {
1566 		return Collections.unmodifiableMap(globalVarOffsetMap);
1567 	}
1568 
1569 	/**
1570 	 * <p>
1571 	 * getGlobalVariableAarrayMap.
1572 	 * </p>
1573 	 *
1574 	 * @return a {@link java.util.Map} object
1575 	 */
1576 	public Map<String, Boolean> getGlobalVariableAarrayMap() {
1577 		return Collections.unmodifiableMap(globalVarAarrayMap);
1578 	}
1579 
1580 	/**
1581 	 * <p>
1582 	 * getFunctionNameSet.
1583 	 * </p>
1584 	 *
1585 	 * @return a {@link java.util.Set} object
1586 	 */
1587 	public Set<String> getFunctionNameSet() {
1588 		assert functionNames != null;
1589 		return Collections.unmodifiableSet(functionNames);
1590 	}
1591 
1592 	/** linenumber stack ... */
1593 	private Deque<Integer> linenoStack = new ArrayDeque<Integer>();
1594 
1595 	/**
1596 	 * Push the current line number onto the line number stack.
1597 	 * This is called by the parser to keep track of the
1598 	 * current source line number. Keeping track of line
1599 	 * numbers this way allows the runtime to report
1600 	 * more meaningful errors by providing source line numbers
1601 	 * within error reports.
1602 	 *
1603 	 * @param lineno The current source line number.
1604 	 */
1605 	public void pushSourceLineNumber(int lineno) {
1606 		linenoStack.push(lineno);
1607 	}
1608 
1609 	/**
1610 	 * <p>
1611 	 * popSourceLineNumber.
1612 	 * </p>
1613 	 *
1614 	 * @param lineno a int
1615 	 */
1616 	public void popSourceLineNumber(int lineno) {
1617 		int tos = linenoStack.pop();
1618 		assert lineno == tos;
1619 	}
1620 
1621 }