From ee8ca9f028829cfa7e717442c7807fe4b29bc0f2 Mon Sep 17 00:00:00 2001
From: Bertrand Martin
Date: Mon, 11 May 2026 18:46:25 +0200
Subject: [PATCH 1/3] Reduce executeTuples bytecode for tuple refactor
---
src/main/java/io/jawk/backend/AVM.java | 728 ++++++++-------
.../java/io/jawk/intermediate/AwkTuples.java | 374 ++++----
.../io/jawk/intermediate/PositionTracker.java | 131 +--
src/main/java/io/jawk/intermediate/Tuple.java | 837 ++++++++++++++----
.../io/jawk/AwkTupleOptimizationTest.java | 28 +-
5 files changed, 1250 insertions(+), 848 deletions(-)
diff --git a/src/main/java/io/jawk/backend/AVM.java b/src/main/java/io/jawk/backend/AVM.java
index d84a815c..9897f387 100644
--- a/src/main/java/io/jawk/backend/AVM.java
+++ b/src/main/java/io/jawk/backend/AVM.java
@@ -54,6 +54,22 @@
import io.jawk.intermediate.Address;
import io.jawk.intermediate.Opcode;
import io.jawk.intermediate.PositionTracker;
+import io.jawk.intermediate.Tuple;
+import io.jawk.intermediate.Tuple.BooleanTuple;
+import io.jawk.intermediate.Tuple.CallFunctionTuple;
+import io.jawk.intermediate.Tuple.ClassTuple;
+import io.jawk.intermediate.Tuple.CountAndAppendTuple;
+import io.jawk.intermediate.Tuple.CountTuple;
+import io.jawk.intermediate.Tuple.DereferenceTuple;
+import io.jawk.intermediate.Tuple.ExtensionTuple;
+import io.jawk.intermediate.Tuple.InputFieldTuple;
+import io.jawk.intermediate.Tuple.LongTuple;
+import io.jawk.intermediate.Tuple.PushDoubleTuple;
+import io.jawk.intermediate.Tuple.PushLongTuple;
+import io.jawk.intermediate.Tuple.PushStringTuple;
+import io.jawk.intermediate.Tuple.RegexTuple;
+import io.jawk.intermediate.Tuple.SubstitutionVariableTuple;
+import io.jawk.intermediate.Tuple.VariableTuple;
import io.jawk.intermediate.UninitializedObject;
import io.jawk.jrt.AssocArray;
import io.jawk.jrt.AwkRuntimeException;
@@ -1008,96 +1024,40 @@ private void executeTuples(PositionTracker position)
try {
while (!position.isEOF()) {
// System_out.println("--> "+position);
- opcode = position.opcode();
+ Tuple tuple = position.current();
+ opcode = tuple.getOpcode();
if (profiling) {
- tupleStartNanos = beforeProfiledTuple(position, opcode);
+ tupleStartNanos = beforeProfiledTuple(tuple, opcode);
}
// switch on OPCODE
switch (opcode) {
case PRINT: {
- // arg[0] = # of items to print on the stack
- // stack[0] = item 1
- // stack[1] = item 2
- // etc.
- long numArgs = position.intArg(0);
- jrt.printDefault(numArgs == 0 ? new Object[] { jrt.jrtGetInputField(0) } : popArguments(numArgs));
+ execPrint((CountTuple) tuple);
position.next();
break;
}
case PRINT_TO_FILE: {
- // arg[0] = # of items to print on the stack
- // arg[1] = true=append, false=overwrite
- // stack[0] = output filename
- // stack[1] = item 1
- // stack[2] = item 2
- // etc.
- boolean append = position.boolArg(1);
- String key = jrt.toAwkString(pop());
- long numArgs = position.intArg(0);
- jrt
- .printToFile(
- key,
- append,
- numArgs == 0 ? new Object[]
- { jrt.jrtGetInputField(0) } : popArguments(numArgs));
+ execPrintToFile((CountAndAppendTuple) tuple);
position.next();
break;
}
case PRINT_TO_PIPE: {
- // arg[0] = # of items to print on the stack
- // stack[0] = command to execute
- // stack[1] = item 1
- // stack[2] = item 2
- // etc.
- String cmd = jrt.toAwkString(pop());
- long numArgs = position.intArg(0);
- jrt
- .printToProcess(
- cmd,
- numArgs == 0 ? new Object[]
- { jrt.jrtGetInputField(0) } : popArguments(numArgs));
+ execPrintToPipe((CountTuple) tuple);
position.next();
break;
}
case PRINTF: {
- // arg[0] = # of items to print on the stack (includes format string)
- // stack[0] = format string
- // stack[1] = item 1
- // etc.
- long numArgs = position.intArg(0);
- Object[] values = popArguments(numArgs - 1);
- String format = jrt.toAwkString(pop());
- jrt.printfDefault(format, values);
+ execPrintf((CountTuple) tuple);
position.next();
break;
}
case PRINTF_TO_FILE: {
- // arg[0] = # of items to print on the stack (includes format string)
- // arg[1] = true=append, false=overwrite
- // stack[0] = output filename
- // stack[1] = format string
- // stack[2] = item 1
- // etc.
- boolean append = position.boolArg(1);
- String key = jrt.toAwkString(pop());
- long numArgs = position.intArg(0);
- Object[] values = popArguments(numArgs - 1);
- String format = jrt.toAwkString(pop());
- jrt.printfToFile(key, append, format, values);
+ execPrintfToFile((CountAndAppendTuple) tuple);
position.next();
break;
}
case PRINTF_TO_PIPE: {
- // arg[0] = # of items to print on the stack (includes format string)
- // stack[0] = command to execute
- // stack[1] = format string
- // stack[2] = item 1
- // etc.
- String cmd = jrt.toAwkString(pop());
- long numArgs = position.intArg(0);
- Object[] values = popArguments(numArgs - 1);
- String format = jrt.toAwkString(pop());
- jrt.printfToProcess(cmd, format, values);
+ execPrintfToPipe((CountTuple) tuple);
position.next();
break;
}
@@ -1106,47 +1066,35 @@ private void executeTuples(PositionTracker position)
// stack[0] = arg1 (format string)
// stack[1] = arg2
// etc.
- long numArgs = position.intArg(0);
+ CountTuple countTuple = (CountTuple) tuple;
+ long numArgs = countTuple.getCount();
push(sprintfFunction(numArgs));
position.next();
break;
}
case LENGTH: {
- // arg[0] = 0==use $0, otherwise, use the stack element
- // stack[0] = element to measure (only if arg[0] != 0)
-
- // print items from the top of the stack
- // # of items
- long num = position.intArg(0);
- if (num == 0) {
- // display $0
- push(jrt.jrtGetInputField(0).toString().length());
- } else {
- Object value = pop();
- if (value instanceof Map) {
- push((long) ((Map, ?>) value).size());
- } else {
- push(jrt.toAwkString(value).length());
- }
- }
+ execLength((CountTuple) tuple);
position.next();
break;
}
case PUSH_LONG: {
// arg[0] = long constant to push onto the stack
- push(position.intArg(0));
+ PushLongTuple pushTuple = (PushLongTuple) tuple;
+ push(pushTuple.getValue());
position.next();
break;
}
case PUSH_DOUBLE: {
// arg[0] = double constant to push onto the stack
- push(position.doubleArg(0));
+ PushDoubleTuple pushTuple = (PushDoubleTuple) tuple;
+ push(pushTuple.getValue());
position.next();
break;
}
case PUSH_STRING: {
// arg[0] = string constant to push onto the stack
- push(position.stringArg(0));
+ PushStringTuple pushTuple = (PushStringTuple) tuple;
+ push(pushTuple.getValue());
position.next();
break;
}
@@ -1165,7 +1113,7 @@ private void executeTuples(PositionTracker position)
// if String, then check for "" or double value of "0"
boolean jump = !jrt.toBoolean(pop());
if (jump) {
- position.jump(position.addressArg());
+ position.jump(tuple.getAddress());
} else {
position.next();
}
@@ -1191,7 +1139,7 @@ private void executeTuples(PositionTracker position)
// if String, then check for "" or double value of "0"
boolean jump = jrt.toBoolean(pop());
if (jump) {
- position.jump(position.addressArg());
+ position.jump(tuple.getAddress());
} else {
position.next();
}
@@ -1238,7 +1186,7 @@ private void executeTuples(PositionTracker position)
case GOTO: {
// arg[0] = address
- position.jump(position.addressArg());
+ position.jump(tuple.getAddress());
break;
}
case NOP: {
@@ -1260,9 +1208,9 @@ private void executeTuples(PositionTracker position)
// arg[0] = offset
// arg[1] = isGlobal
// stack[0] = value
+ VariableTuple variableTuple = (VariableTuple) tuple;
Object value = pop();
- boolean isGlobal = position.boolArg(1);
- assign(position.intArg(0), value, isGlobal, position);
+ assign(variableTuple.getVariableOffset(), value, variableTuple.isGlobal(), position);
position.next();
break;
}
@@ -1276,8 +1224,9 @@ private void executeTuples(PositionTracker position)
if (rhs == null) {
rhs = BLANK;
}
- long offset = position.intArg(0);
- boolean isGlobal = position.boolArg(1);
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ long offset = variableTuple.getVariableOffset();
+ boolean isGlobal = variableTuple.isGlobal();
assignArray(offset, arrIdx, rhs, isGlobal);
position.next();
break;
@@ -1311,8 +1260,9 @@ private void executeTuples(PositionTracker position)
if (rhs == null) {
rhs = BLANK;
}
- long offset = position.intArg(0);
- boolean isGlobal = position.boolArg(1);
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ long offset = variableTuple.getVariableOffset();
+ boolean isGlobal = variableTuple.isGlobal();
double val = JRT.toDouble(rhs);
@@ -1441,8 +1391,10 @@ private void executeTuples(PositionTracker position)
// arg[0] = offset
// arg[1] = isGlobal
// stack[0] = value
- boolean isGlobal = position.boolArg(1);
- Object o1 = runtimeStack.getVariable(position.intArg(0), isGlobal);
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ long offset = variableTuple.getVariableOffset();
+ boolean isGlobal = variableTuple.isGlobal();
+ Object o1 = runtimeStack.getVariable(offset, isGlobal);
if (o1 == null) {
o1 = BLANK;
}
@@ -1475,10 +1427,10 @@ private void executeTuples(PositionTracker position)
if (JRT.isActuallyLong(ans)) {
long integral = (long) Math.rint(ans);
push(integral);
- runtimeStack.setVariable(position.intArg(0), integral, isGlobal);
+ runtimeStack.setVariable(offset, integral, isGlobal);
} else {
push(ans);
- runtimeStack.setVariable(position.intArg(0), ans, isGlobal);
+ runtimeStack.setVariable(offset, ans, isGlobal);
}
position.next();
break;
@@ -1532,14 +1484,16 @@ private void executeTuples(PositionTracker position)
case INC: {
// arg[0] = offset
// arg[1] = isGlobal
- inc(position.intArg(0), position.boolArg(1));
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ inc(variableTuple.getVariableOffset(), variableTuple.isGlobal());
position.next();
break;
}
case DEC: {
// arg[0] = offset
// arg[1] = isGlobal
- dec(position.intArg(0), position.boolArg(1));
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ dec(variableTuple.getVariableOffset(), variableTuple.isGlobal());
position.next();
break;
}
@@ -1547,7 +1501,8 @@ private void executeTuples(PositionTracker position)
// arg[0] = offset
// arg[1] = isGlobal
pop();
- push(inc(position.intArg(0), position.boolArg(1)));
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ push(inc(variableTuple.getVariableOffset(), variableTuple.isGlobal()));
position.next();
break;
}
@@ -1555,7 +1510,8 @@ private void executeTuples(PositionTracker position)
// arg[0] = offset
// arg[1] = isGlobal
pop();
- push(dec(position.intArg(0), position.boolArg(1)));
+ VariableTuple variableTuple = (VariableTuple) tuple;
+ push(dec(variableTuple.getVariableOffset(), variableTuple.isGlobal()));
position.next();
break;
}
@@ -1563,8 +1519,9 @@ private void executeTuples(PositionTracker position)
// arg[0] = offset
// arg[1] = isGlobal
// stack[0] = array index
- boolean isGlobal = position.boolArg(1);
- Map
*/
public void pop() {
- queue.add(new Tuple(Opcode.POP));
+ queue.add(new Tuple.NoOperandTuple(Opcode.POP));
}
/**
@@ -118,13 +118,13 @@ public void pop() {
*/
public void push(Object o) {
if (o instanceof String) {
- queue.add(new Tuple(Opcode.PUSH_STRING, o.toString()));
+ queue.add(new Tuple.PushStringTuple(o.toString()));
} else if (o instanceof Integer) {
- queue.add(new Tuple(Opcode.PUSH_LONG, (long) (Integer) o));
+ queue.add(new Tuple.PushLongTuple((long) (Integer) o));
} else if (o instanceof Long) {
- queue.add(new Tuple(Opcode.PUSH_LONG, (long) (Long) o));
+ queue.add(new Tuple.PushLongTuple((long) (Long) o));
} else if (o instanceof Double) {
- queue.add(new Tuple(Opcode.PUSH_DOUBLE, (Double) o));
+ queue.add(new Tuple.PushDoubleTuple((Double) o));
}
}
@@ -136,7 +136,7 @@ public void push(Object o) {
* @param address a {@link io.jawk.intermediate.Address} object
*/
public void ifFalse(Address address) {
- queue.add(new Tuple(Opcode.IFFALSE, address));
+ queue.add(new Tuple.AddressTuple(Opcode.IFFALSE, address));
}
/**
@@ -145,7 +145,7 @@ public void ifFalse(Address address) {
*
*/
public void toNumber() {
- queue.add(new Tuple(Opcode.TO_NUMBER));
+ queue.add(new Tuple.NoOperandTuple(Opcode.TO_NUMBER));
}
/**
@@ -156,7 +156,7 @@ public void toNumber() {
* @param address a {@link io.jawk.intermediate.Address} object
*/
public void ifTrue(Address address) {
- queue.add(new Tuple(Opcode.IFTRUE, address));
+ queue.add(new Tuple.AddressTuple(Opcode.IFTRUE, address));
}
/**
@@ -167,7 +167,7 @@ public void ifTrue(Address address) {
* @param address a {@link io.jawk.intermediate.Address} object
*/
public void gotoAddress(Address address) {
- queue.add(new Tuple(Opcode.GOTO, address));
+ queue.add(new Tuple.AddressTuple(Opcode.GOTO, address));
}
/**
@@ -201,7 +201,7 @@ public AwkTuples address(Address address) {
*
*/
public void nop() {
- queue.add(new Tuple(Opcode.NOP));
+ queue.add(new Tuple.NoOperandTuple(Opcode.NOP));
}
/**
@@ -212,7 +212,7 @@ public void nop() {
* @param numExprs a int
*/
public void print(int numExprs) {
- queue.add(new Tuple(Opcode.PRINT, numExprs));
+ queue.add(new Tuple.CountTuple(Opcode.PRINT, numExprs));
}
/**
@@ -224,7 +224,7 @@ public void print(int numExprs) {
* @param append a boolean
*/
public void printToFile(int numExprs, boolean append) {
- queue.add(new Tuple(Opcode.PRINT_TO_FILE, numExprs, append));
+ queue.add(new Tuple.CountAndAppendTuple(Opcode.PRINT_TO_FILE, numExprs, append));
}
/**
@@ -235,7 +235,7 @@ public void printToFile(int numExprs, boolean append) {
* @param numExprs a int
*/
public void printToPipe(int numExprs) {
- queue.add(new Tuple(Opcode.PRINT_TO_PIPE, numExprs));
+ queue.add(new Tuple.CountTuple(Opcode.PRINT_TO_PIPE, numExprs));
}
/**
@@ -246,7 +246,7 @@ public void printToPipe(int numExprs) {
* @param numExprs a int
*/
public void printf(int numExprs) {
- queue.add(new Tuple(Opcode.PRINTF, numExprs));
+ queue.add(new Tuple.CountTuple(Opcode.PRINTF, numExprs));
}
/**
@@ -258,7 +258,7 @@ public void printf(int numExprs) {
* @param append a boolean
*/
public void printfToFile(int numExprs, boolean append) {
- queue.add(new Tuple(Opcode.PRINTF_TO_FILE, numExprs, append));
+ queue.add(new Tuple.CountAndAppendTuple(Opcode.PRINTF_TO_FILE, numExprs, append));
}
/**
@@ -269,7 +269,7 @@ public void printfToFile(int numExprs, boolean append) {
* @param numExprs a int
*/
public void printfToPipe(int numExprs) {
- queue.add(new Tuple(Opcode.PRINTF_TO_PIPE, numExprs));
+ queue.add(new Tuple.CountTuple(Opcode.PRINTF_TO_PIPE, numExprs));
}
/**
@@ -280,7 +280,7 @@ public void printfToPipe(int numExprs) {
* @param numExprs a int
*/
public void sprintf(int numExprs) {
- queue.add(new Tuple(Opcode.SPRINTF, numExprs));
+ queue.add(new Tuple.CountTuple(Opcode.SPRINTF, numExprs));
}
/**
@@ -291,7 +291,7 @@ public void sprintf(int numExprs) {
* @param numExprs a int
*/
public void length(int numExprs) {
- queue.add(new Tuple(Opcode.LENGTH, numExprs));
+ queue.add(new Tuple.CountTuple(Opcode.LENGTH, numExprs));
}
/**
@@ -300,7 +300,7 @@ public void length(int numExprs) {
*
*/
public void concat() {
- queue.add(new Tuple(Opcode.CONCAT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.CONCAT));
}
/**
@@ -312,7 +312,7 @@ public void concat() {
* @param isGlobal a boolean
*/
public void assign(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.ASSIGN, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.ASSIGN, offset, isGlobal));
}
/**
@@ -324,14 +324,14 @@ public void assign(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void assignArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.ASSIGN_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.ASSIGN_ARRAY, offset, isGlobal));
}
/**
* Assigns a value to a stack-provided associative-array element.
*/
public void assignMapElement() {
- queue.add(new Tuple(Opcode.ASSIGN_MAP_ELEMENT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.ASSIGN_MAP_ELEMENT));
}
/**
@@ -340,7 +340,7 @@ public void assignMapElement() {
*
*/
public void assignAsInput() {
- queue.add(new Tuple(Opcode.ASSIGN_AS_INPUT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.ASSIGN_AS_INPUT));
}
/**
@@ -358,7 +358,7 @@ public void markEvalTupleStream() {
*
*/
public void assignAsInputField() {
- queue.add(new Tuple(Opcode.ASSIGN_AS_INPUT_FIELD));
+ queue.add(new Tuple.NoOperandTuple(Opcode.ASSIGN_AS_INPUT_FIELD));
}
/**
@@ -371,7 +371,7 @@ public void assignAsInputField() {
* @param isGlobal a boolean
*/
public void dereference(int offset, boolean isArray, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DEREFERENCE, offset, isArray, isGlobal));
+ queue.add(new Tuple.DereferenceTuple(offset, isArray, isGlobal));
}
/**
@@ -383,7 +383,7 @@ public void dereference(int offset, boolean isArray, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void plusEq(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.PLUS_EQ, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignTuple(Opcode.PLUS_EQ, offset, isGlobal));
}
/**
@@ -395,7 +395,7 @@ public void plusEq(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void minusEq(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.MINUS_EQ, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignTuple(Opcode.MINUS_EQ, offset, isGlobal));
}
/**
@@ -407,7 +407,7 @@ public void minusEq(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void multEq(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.MULT_EQ, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignTuple(Opcode.MULT_EQ, offset, isGlobal));
}
/**
@@ -419,7 +419,7 @@ public void multEq(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void divEq(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DIV_EQ, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignTuple(Opcode.DIV_EQ, offset, isGlobal));
}
/**
@@ -431,7 +431,7 @@ public void divEq(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void modEq(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.MOD_EQ, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignTuple(Opcode.MOD_EQ, offset, isGlobal));
}
/**
@@ -443,7 +443,7 @@ public void modEq(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void powEq(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.POW_EQ, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignTuple(Opcode.POW_EQ, offset, isGlobal));
}
/**
@@ -455,14 +455,14 @@ public void powEq(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void plusEqArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.PLUS_EQ_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignArrayTuple(Opcode.PLUS_EQ_ARRAY, offset, isGlobal));
}
/**
* Applies {@code +=} to a stack-provided associative-array element.
*/
public void plusEqMapElement() {
- queue.add(new Tuple(Opcode.PLUS_EQ_MAP_ELEMENT));
+ queue.add(new Tuple.CompoundAssignMapElementTuple(Opcode.PLUS_EQ_MAP_ELEMENT));
}
/**
@@ -474,14 +474,14 @@ public void plusEqMapElement() {
* @param isGlobal a boolean
*/
public void minusEqArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.MINUS_EQ_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignArrayTuple(Opcode.MINUS_EQ_ARRAY, offset, isGlobal));
}
/**
* Applies {@code -=} to a stack-provided associative-array element.
*/
public void minusEqMapElement() {
- queue.add(new Tuple(Opcode.MINUS_EQ_MAP_ELEMENT));
+ queue.add(new Tuple.CompoundAssignMapElementTuple(Opcode.MINUS_EQ_MAP_ELEMENT));
}
/**
@@ -493,14 +493,14 @@ public void minusEqMapElement() {
* @param isGlobal a boolean
*/
public void multEqArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.MULT_EQ_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignArrayTuple(Opcode.MULT_EQ_ARRAY, offset, isGlobal));
}
/**
* Applies {@code *=} to a stack-provided associative-array element.
*/
public void multEqMapElement() {
- queue.add(new Tuple(Opcode.MULT_EQ_MAP_ELEMENT));
+ queue.add(new Tuple.CompoundAssignMapElementTuple(Opcode.MULT_EQ_MAP_ELEMENT));
}
/**
@@ -512,14 +512,14 @@ public void multEqMapElement() {
* @param isGlobal a boolean
*/
public void divEqArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DIV_EQ_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignArrayTuple(Opcode.DIV_EQ_ARRAY, offset, isGlobal));
}
/**
* Applies {@code /=} to a stack-provided associative-array element.
*/
public void divEqMapElement() {
- queue.add(new Tuple(Opcode.DIV_EQ_MAP_ELEMENT));
+ queue.add(new Tuple.CompoundAssignMapElementTuple(Opcode.DIV_EQ_MAP_ELEMENT));
}
/**
@@ -531,14 +531,14 @@ public void divEqMapElement() {
* @param isGlobal a boolean
*/
public void modEqArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.MOD_EQ_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignArrayTuple(Opcode.MOD_EQ_ARRAY, offset, isGlobal));
}
/**
* Applies {@code %=} to a stack-provided associative-array element.
*/
public void modEqMapElement() {
- queue.add(new Tuple(Opcode.MOD_EQ_MAP_ELEMENT));
+ queue.add(new Tuple.CompoundAssignMapElementTuple(Opcode.MOD_EQ_MAP_ELEMENT));
}
/**
@@ -550,7 +550,7 @@ public void modEqMapElement() {
* @param isGlobal a boolean
*/
public void powEqArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.POW_EQ_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.CompoundAssignArrayTuple(Opcode.POW_EQ_ARRAY, offset, isGlobal));
}
/**
@@ -558,7 +558,7 @@ public void powEqArray(int offset, boolean isGlobal) {
* element.
*/
public void powEqMapElement() {
- queue.add(new Tuple(Opcode.POW_EQ_MAP_ELEMENT));
+ queue.add(new Tuple.CompoundAssignMapElementTuple(Opcode.POW_EQ_MAP_ELEMENT));
}
/**
@@ -567,7 +567,7 @@ public void powEqMapElement() {
*
*/
public void plusEqInputField() {
- queue.add(new Tuple(Opcode.PLUS_EQ_INPUT_FIELD));
+ queue.add(new Tuple.CompoundAssignInputFieldTuple(Opcode.PLUS_EQ_INPUT_FIELD));
}
/**
@@ -576,7 +576,7 @@ public void plusEqInputField() {
*
*/
public void minusEqInputField() {
- queue.add(new Tuple(Opcode.MINUS_EQ_INPUT_FIELD));
+ queue.add(new Tuple.CompoundAssignInputFieldTuple(Opcode.MINUS_EQ_INPUT_FIELD));
}
/**
@@ -585,7 +585,7 @@ public void minusEqInputField() {
*
*/
public void multEqInputField() {
- queue.add(new Tuple(Opcode.MULT_EQ_INPUT_FIELD));
+ queue.add(new Tuple.CompoundAssignInputFieldTuple(Opcode.MULT_EQ_INPUT_FIELD));
}
/**
@@ -594,7 +594,7 @@ public void multEqInputField() {
*
*/
public void divEqInputField() {
- queue.add(new Tuple(Opcode.DIV_EQ_INPUT_FIELD));
+ queue.add(new Tuple.CompoundAssignInputFieldTuple(Opcode.DIV_EQ_INPUT_FIELD));
}
/**
@@ -603,7 +603,7 @@ public void divEqInputField() {
*
*/
public void modEqInputField() {
- queue.add(new Tuple(Opcode.MOD_EQ_INPUT_FIELD));
+ queue.add(new Tuple.CompoundAssignInputFieldTuple(Opcode.MOD_EQ_INPUT_FIELD));
}
/**
@@ -612,7 +612,7 @@ public void modEqInputField() {
*
*/
public void powEqInputField() {
- queue.add(new Tuple(Opcode.POW_EQ_INPUT_FIELD));
+ queue.add(new Tuple.CompoundAssignInputFieldTuple(Opcode.POW_EQ_INPUT_FIELD));
}
/**
@@ -623,7 +623,7 @@ public void powEqInputField() {
* @param num a int
*/
public void srand(int num) {
- queue.add(new Tuple(Opcode.SRAND, num));
+ queue.add(new Tuple.CountTuple(Opcode.SRAND, num));
}
/**
@@ -632,7 +632,7 @@ public void srand(int num) {
*
*/
public void rand() {
- queue.add(new Tuple(Opcode.RAND));
+ queue.add(new Tuple.NoOperandTuple(Opcode.RAND));
}
/**
@@ -641,7 +641,7 @@ public void rand() {
*
*/
public void intFunc() {
- queue.add(new Tuple(Opcode.INTFUNC));
+ queue.add(new Tuple.NoOperandTuple(Opcode.INTFUNC));
}
/**
@@ -650,7 +650,7 @@ public void intFunc() {
*
*/
public void sqrt() {
- queue.add(new Tuple(Opcode.SQRT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.SQRT));
}
/**
@@ -659,7 +659,7 @@ public void sqrt() {
*
*/
public void log() {
- queue.add(new Tuple(Opcode.LOG));
+ queue.add(new Tuple.NoOperandTuple(Opcode.LOG));
}
/**
@@ -668,7 +668,7 @@ public void log() {
*
*/
public void exp() {
- queue.add(new Tuple(Opcode.EXP));
+ queue.add(new Tuple.NoOperandTuple(Opcode.EXP));
}
/**
@@ -677,7 +677,7 @@ public void exp() {
*
*/
public void sin() {
- queue.add(new Tuple(Opcode.SIN));
+ queue.add(new Tuple.NoOperandTuple(Opcode.SIN));
}
/**
@@ -686,7 +686,7 @@ public void sin() {
*
*/
public void cos() {
- queue.add(new Tuple(Opcode.COS));
+ queue.add(new Tuple.NoOperandTuple(Opcode.COS));
}
/**
@@ -695,7 +695,7 @@ public void cos() {
*
*/
public void atan2() {
- queue.add(new Tuple(Opcode.ATAN2));
+ queue.add(new Tuple.NoOperandTuple(Opcode.ATAN2));
}
/**
@@ -704,7 +704,7 @@ public void atan2() {
*
*/
public void match() {
- queue.add(new Tuple(Opcode.MATCH));
+ queue.add(new Tuple.NoOperandTuple(Opcode.MATCH));
}
/**
@@ -713,7 +713,7 @@ public void match() {
*
*/
public void index() {
- queue.add(new Tuple(Opcode.INDEX));
+ queue.add(new Tuple.NoOperandTuple(Opcode.INDEX));
}
/**
@@ -724,7 +724,7 @@ public void index() {
* @param isGsub a boolean
*/
public void subForDollar0(boolean isGsub) {
- queue.add(new Tuple(Opcode.SUB_FOR_DOLLAR_0, isGsub));
+ queue.add(new Tuple.BooleanTuple(Opcode.SUB_FOR_DOLLAR_0, isGsub));
}
/**
@@ -735,7 +735,7 @@ public void subForDollar0(boolean isGsub) {
* @param isGsub a boolean
*/
public void subForDollarReference(boolean isGsub) {
- queue.add(new Tuple(Opcode.SUB_FOR_DOLLAR_REFERENCE, isGsub));
+ queue.add(new Tuple.BooleanTuple(Opcode.SUB_FOR_DOLLAR_REFERENCE, isGsub));
}
/**
@@ -748,7 +748,7 @@ public void subForDollarReference(boolean isGsub) {
* @param isGsub a boolean
*/
public void subForVariable(int offset, boolean isGlobal, boolean isGsub) {
- queue.add(new Tuple(Opcode.SUB_FOR_VARIABLE, offset, isGlobal, isGsub));
+ queue.add(new Tuple.SubstitutionVariableTuple(Opcode.SUB_FOR_VARIABLE, offset, isGlobal, isGsub));
}
/**
@@ -761,7 +761,7 @@ public void subForVariable(int offset, boolean isGlobal, boolean isGsub) {
* @param isGsub a boolean
*/
public void subForArrayReference(int offset, boolean isGlobal, boolean isGsub) {
- queue.add(new Tuple(Opcode.SUB_FOR_ARRAY_REFERENCE, offset, isGlobal, isGsub));
+ queue.add(new Tuple.SubstitutionVariableTuple(Opcode.SUB_FOR_ARRAY_REFERENCE, offset, isGlobal, isGsub));
}
/**
@@ -771,7 +771,7 @@ public void subForArrayReference(int offset, boolean isGlobal, boolean isGsub) {
* @param isGsub {@code true} for {@code gsub}, {@code false} for {@code sub}
*/
public void subForMapReference(boolean isGsub) {
- queue.add(new Tuple(Opcode.SUB_FOR_MAP_REFERENCE, isGsub));
+ queue.add(new Tuple.BooleanTuple(Opcode.SUB_FOR_MAP_REFERENCE, isGsub));
}
/**
@@ -782,7 +782,7 @@ public void subForMapReference(boolean isGsub) {
* @param numargs a int
*/
public void split(int numargs) {
- queue.add(new Tuple(Opcode.SPLIT, numargs));
+ queue.add(new Tuple.CountTuple(Opcode.SPLIT, numargs));
}
/**
@@ -793,7 +793,7 @@ public void split(int numargs) {
* @param numargs a int
*/
public void substr(int numargs) {
- queue.add(new Tuple(Opcode.SUBSTR, numargs));
+ queue.add(new Tuple.CountTuple(Opcode.SUBSTR, numargs));
}
/**
@@ -802,7 +802,7 @@ public void substr(int numargs) {
*
*/
public void tolower() {
- queue.add(new Tuple(Opcode.TOLOWER));
+ queue.add(new Tuple.NoOperandTuple(Opcode.TOLOWER));
}
/**
@@ -811,7 +811,7 @@ public void tolower() {
*
*/
public void toupper() {
- queue.add(new Tuple(Opcode.TOUPPER));
+ queue.add(new Tuple.NoOperandTuple(Opcode.TOUPPER));
}
/**
@@ -820,7 +820,7 @@ public void toupper() {
*
*/
public void system() {
- queue.add(new Tuple(Opcode.SYSTEM));
+ queue.add(new Tuple.NoOperandTuple(Opcode.SYSTEM));
}
/**
@@ -829,7 +829,7 @@ public void system() {
*
*/
public void swap() {
- queue.add(new Tuple(Opcode.SWAP));
+ queue.add(new Tuple.NoOperandTuple(Opcode.SWAP));
}
/**
@@ -838,7 +838,7 @@ public void swap() {
*
*/
public void add() {
- queue.add(new Tuple(Opcode.ADD));
+ queue.add(new Tuple.NoOperandTuple(Opcode.ADD));
}
/**
@@ -847,7 +847,7 @@ public void add() {
*
*/
public void subtract() {
- queue.add(new Tuple(Opcode.SUBTRACT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.SUBTRACT));
}
/**
@@ -856,7 +856,7 @@ public void subtract() {
*
*/
public void multiply() {
- queue.add(new Tuple(Opcode.MULTIPLY));
+ queue.add(new Tuple.NoOperandTuple(Opcode.MULTIPLY));
}
/**
@@ -865,7 +865,7 @@ public void multiply() {
*
*/
public void divide() {
- queue.add(new Tuple(Opcode.DIVIDE));
+ queue.add(new Tuple.NoOperandTuple(Opcode.DIVIDE));
}
/**
@@ -874,7 +874,7 @@ public void divide() {
*
*/
public void mod() {
- queue.add(new Tuple(Opcode.MOD));
+ queue.add(new Tuple.NoOperandTuple(Opcode.MOD));
}
/**
@@ -883,7 +883,7 @@ public void mod() {
*
*/
public void pow() {
- queue.add(new Tuple(Opcode.POW));
+ queue.add(new Tuple.NoOperandTuple(Opcode.POW));
}
/**
@@ -895,7 +895,7 @@ public void pow() {
* @param isGlobal a boolean
*/
public void inc(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.INC, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.INC, offset, isGlobal));
}
/**
@@ -907,7 +907,7 @@ public void inc(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void dec(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DEC, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.DEC, offset, isGlobal));
}
/**
@@ -919,7 +919,7 @@ public void dec(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void postInc(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.POSTINC, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.POSTINC, offset, isGlobal));
}
/**
@@ -931,7 +931,7 @@ public void postInc(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void postDec(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.POSTDEC, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.POSTDEC, offset, isGlobal));
}
/**
@@ -943,14 +943,14 @@ public void postDec(int offset, boolean isGlobal) {
* @param isGlobal a boolean
*/
public void incArrayRef(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.INC_ARRAY_REF, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.INC_ARRAY_REF, offset, isGlobal));
}
/**
* Increments a stack-provided associative-array element reference.
*/
public void incMapRef() {
- queue.add(new Tuple(Opcode.INC_MAP_REF));
+ queue.add(new Tuple.NoOperandTuple(Opcode.INC_MAP_REF));
}
/**
@@ -962,14 +962,14 @@ public void incMapRef() {
* @param isGlobal a boolean
*/
public void decArrayRef(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DEC_ARRAY_REF, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.DEC_ARRAY_REF, offset, isGlobal));
}
/**
* Decrements a stack-provided associative-array element reference.
*/
public void decMapRef() {
- queue.add(new Tuple(Opcode.DEC_MAP_REF));
+ queue.add(new Tuple.NoOperandTuple(Opcode.DEC_MAP_REF));
}
/**
@@ -978,7 +978,7 @@ public void decMapRef() {
*
*/
public void incDollarRef() {
- queue.add(new Tuple(Opcode.INC_DOLLAR_REF));
+ queue.add(new Tuple.NoOperandTuple(Opcode.INC_DOLLAR_REF));
}
/**
@@ -987,7 +987,7 @@ public void incDollarRef() {
*
*/
public void decDollarRef() {
- queue.add(new Tuple(Opcode.DEC_DOLLAR_REF));
+ queue.add(new Tuple.NoOperandTuple(Opcode.DEC_DOLLAR_REF));
}
/**
@@ -996,7 +996,7 @@ public void decDollarRef() {
*
*/
public void dup() {
- queue.add(new Tuple(Opcode.DUP));
+ queue.add(new Tuple.NoOperandTuple(Opcode.DUP));
}
/**
@@ -1005,7 +1005,7 @@ public void dup() {
*
*/
public void not() {
- queue.add(new Tuple(Opcode.NOT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.NOT));
}
/**
@@ -1014,7 +1014,7 @@ public void not() {
*
*/
public void negate() {
- queue.add(new Tuple(Opcode.NEGATE));
+ queue.add(new Tuple.NoOperandTuple(Opcode.NEGATE));
}
/**
@@ -1023,7 +1023,7 @@ public void negate() {
*
*/
public void unaryPlus() {
- queue.add(new Tuple(Opcode.UNARY_PLUS));
+ queue.add(new Tuple.NoOperandTuple(Opcode.UNARY_PLUS));
}
/**
@@ -1032,7 +1032,7 @@ public void unaryPlus() {
*
*/
public void cmpEq() {
- queue.add(new Tuple(Opcode.CMP_EQ));
+ queue.add(new Tuple.NoOperandTuple(Opcode.CMP_EQ));
}
/**
@@ -1041,7 +1041,7 @@ public void cmpEq() {
*
*/
public void cmpLt() {
- queue.add(new Tuple(Opcode.CMP_LT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.CMP_LT));
}
/**
@@ -1050,7 +1050,7 @@ public void cmpLt() {
*
*/
public void cmpGt() {
- queue.add(new Tuple(Opcode.CMP_GT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.CMP_GT));
}
/**
@@ -1059,7 +1059,7 @@ public void cmpGt() {
*
*/
public void matches() {
- queue.add(new Tuple(Opcode.MATCHES));
+ queue.add(new Tuple.NoOperandTuple(Opcode.MATCHES));
}
/**
@@ -1068,7 +1068,7 @@ public void matches() {
*
*/
public void dereferenceArray() {
- queue.add(new Tuple(Opcode.DEREF_ARRAY));
+ queue.add(new Tuple.NoOperandTuple(Opcode.DEREF_ARRAY));
}
/**
@@ -1076,7 +1076,7 @@ public void dereferenceArray() {
* the key is missing.
*/
public void peekArrayElement() {
- queue.add(new Tuple(Opcode.PEEK_ARRAY_ELEMENT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.PEEK_ARRAY_ELEMENT));
}
/**
@@ -1084,7 +1084,7 @@ public void peekArrayElement() {
* needed.
*/
public void ensureArrayElement() {
- queue.add(new Tuple(Opcode.ENSURE_ARRAY_ELEMENT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.ENSURE_ARRAY_ELEMENT));
}
/**
@@ -1093,7 +1093,7 @@ public void ensureArrayElement() {
*
*/
public void keylist() {
- queue.add(new Tuple(Opcode.KEYLIST));
+ queue.add(new Tuple.NoOperandTuple(Opcode.KEYLIST));
}
/**
@@ -1104,7 +1104,7 @@ public void keylist() {
* @param address a {@link io.jawk.intermediate.Address} object
*/
public void isEmptyList(Address address) {
- queue.add(new Tuple(Opcode.IS_EMPTY_KEYLIST, address));
+ queue.add(new Tuple.AddressTuple(Opcode.IS_EMPTY_KEYLIST, address));
}
/**
@@ -1113,7 +1113,7 @@ public void isEmptyList(Address address) {
*
*/
public void getFirstAndRemoveFromList() {
- queue.add(new Tuple(Opcode.GET_FIRST_AND_REMOVE_FROM_KEYLIST));
+ queue.add(new Tuple.NoOperandTuple(Opcode.GET_FIRST_AND_REMOVE_FROM_KEYLIST));
}
/**
@@ -1125,7 +1125,7 @@ public void getFirstAndRemoveFromList() {
* @return a boolean
*/
public boolean checkClass(Class> cls) {
- queue.add(new Tuple(Opcode.CHECK_CLASS, cls));
+ queue.add(new Tuple.ClassTuple(cls));
return true;
}
@@ -1135,7 +1135,7 @@ public boolean checkClass(Class> cls) {
*
*/
public void getInputField() {
- queue.add(new Tuple(Opcode.GET_INPUT_FIELD));
+ queue.add(new Tuple.NoOperandTuple(Opcode.GET_INPUT_FIELD));
}
/**
@@ -1146,7 +1146,7 @@ public void getInputField() {
* @param fieldIndex a long
*/
public void getInputField(long fieldIndex) {
- queue.add(new Tuple(Opcode.GET_INPUT_FIELD_CONST, fieldIndex));
+ queue.add(new Tuple.InputFieldTuple(fieldIndex));
}
/**
@@ -1157,7 +1157,7 @@ public void getInputField(long fieldIndex) {
* @param address a {@link io.jawk.intermediate.Address} object
*/
public void consumeInput(Address address) {
- queue.add(new Tuple(Opcode.CONSUME_INPUT, address));
+ queue.add(new Tuple.AddressTuple(Opcode.CONSUME_INPUT, address));
}
/**
@@ -1166,7 +1166,7 @@ public void consumeInput(Address address) {
*
*/
public void getlineInput() {
- queue.add(new Tuple(Opcode.GETLINE_INPUT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.GETLINE_INPUT));
}
/**
@@ -1175,7 +1175,7 @@ public void getlineInput() {
*
*/
public void getlineInputToTarget() {
- queue.add(new Tuple(Opcode.GETLINE_INPUT_TO_TARGET));
+ queue.add(new Tuple.NoOperandTuple(Opcode.GETLINE_INPUT_TO_TARGET));
}
/**
@@ -1184,7 +1184,7 @@ public void getlineInputToTarget() {
*
*/
public void useAsFileInput() {
- queue.add(new Tuple(Opcode.USE_AS_FILE_INPUT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.USE_AS_FILE_INPUT));
}
/**
@@ -1193,7 +1193,7 @@ public void useAsFileInput() {
*
*/
public void useAsCommandInput() {
- queue.add(new Tuple(Opcode.USE_AS_COMMAND_INPUT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.USE_AS_COMMAND_INPUT));
}
/**
@@ -1204,7 +1204,7 @@ public void useAsCommandInput() {
* @param offset a int
*/
public void nfOffset(int offset) {
- queue.add(new Tuple(Opcode.NF_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.NF_OFFSET, offset));
}
/**
@@ -1215,7 +1215,7 @@ public void nfOffset(int offset) {
* @param offset a int
*/
public void nrOffset(int offset) {
- queue.add(new Tuple(Opcode.NR_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.NR_OFFSET, offset));
}
/**
@@ -1226,7 +1226,7 @@ public void nrOffset(int offset) {
* @param offset a int
*/
public void fnrOffset(int offset) {
- queue.add(new Tuple(Opcode.FNR_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.FNR_OFFSET, offset));
}
/**
@@ -1237,7 +1237,7 @@ public void fnrOffset(int offset) {
* @param offset a int
*/
public void fsOffset(int offset) {
- queue.add(new Tuple(Opcode.FS_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.FS_OFFSET, offset));
}
/**
@@ -1248,7 +1248,7 @@ public void fsOffset(int offset) {
* @param offset a int
*/
public void rsOffset(int offset) {
- queue.add(new Tuple(Opcode.RS_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.RS_OFFSET, offset));
}
/**
@@ -1259,7 +1259,7 @@ public void rsOffset(int offset) {
* @param offset a int
*/
public void ofsOffset(int offset) {
- queue.add(new Tuple(Opcode.OFS_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.OFS_OFFSET, offset));
}
/**
@@ -1270,7 +1270,7 @@ public void ofsOffset(int offset) {
* @param offset a int
*/
public void orsOffset(int offset) {
- queue.add(new Tuple(Opcode.ORS_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.ORS_OFFSET, offset));
}
/**
@@ -1281,7 +1281,7 @@ public void orsOffset(int offset) {
* @param offset a int
*/
public void rstartOffset(int offset) {
- queue.add(new Tuple(Opcode.RSTART_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.RSTART_OFFSET, offset));
}
/**
@@ -1292,7 +1292,7 @@ public void rstartOffset(int offset) {
* @param offset a int
*/
public void rlengthOffset(int offset) {
- queue.add(new Tuple(Opcode.RLENGTH_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.RLENGTH_OFFSET, offset));
}
/**
@@ -1303,7 +1303,7 @@ public void rlengthOffset(int offset) {
* @param offset a int
*/
public void filenameOffset(int offset) {
- queue.add(new Tuple(Opcode.FILENAME_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.FILENAME_OFFSET, offset));
}
/**
@@ -1314,7 +1314,7 @@ public void filenameOffset(int offset) {
* @param offset a int
*/
public void subsepOffset(int offset) {
- queue.add(new Tuple(Opcode.SUBSEP_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.SUBSEP_OFFSET, offset));
}
/**
@@ -1325,7 +1325,7 @@ public void subsepOffset(int offset) {
* @param offset a int
*/
public void convfmtOffset(int offset) {
- queue.add(new Tuple(Opcode.CONVFMT_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.CONVFMT_OFFSET, offset));
}
/**
@@ -1336,7 +1336,7 @@ public void convfmtOffset(int offset) {
* @param offset a int
*/
public void ofmtOffset(int offset) {
- queue.add(new Tuple(Opcode.OFMT_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.OFMT_OFFSET, offset));
}
/**
@@ -1347,7 +1347,7 @@ public void ofmtOffset(int offset) {
* @param offset a int
*/
public void environOffset(int offset) {
- queue.add(new Tuple(Opcode.ENVIRON_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.ENVIRON_OFFSET, offset));
}
/**
@@ -1358,7 +1358,7 @@ public void environOffset(int offset) {
* @param offset a int
*/
public void argcOffset(int offset) {
- queue.add(new Tuple(Opcode.ARGC_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.ARGC_OFFSET, offset));
}
/**
@@ -1369,148 +1369,148 @@ public void argcOffset(int offset) {
* @param offset a int
*/
public void argvOffset(int offset) {
- queue.add(new Tuple(Opcode.ARGV_OFFSET, offset));
+ queue.add(new Tuple.LongTuple(Opcode.ARGV_OFFSET, offset));
}
// JRT-managed special variable helpers
/** Pushes the current value of {@code NF} onto the operand stack. */
public void pushNF() {
- queue.add(new Tuple(Opcode.PUSH_NF));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_NF));
}
/** Assigns the top-of-stack value to {@code NF}. */
public void assignNF() {
- queue.add(new Tuple(Opcode.ASSIGN_NF));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_NF));
}
/** Pushes the current value of {@code NR} onto the operand stack. */
public void pushNR() {
- queue.add(new Tuple(Opcode.PUSH_NR));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_NR));
}
/** Assigns the top-of-stack value to {@code NR}. */
public void assignNR() {
- queue.add(new Tuple(Opcode.ASSIGN_NR));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_NR));
}
/** Pushes the current value of {@code FNR} onto the operand stack. */
public void pushFNR() {
- queue.add(new Tuple(Opcode.PUSH_FNR));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_FNR));
}
/** Assigns the top-of-stack value to {@code FNR}. */
public void assignFNR() {
- queue.add(new Tuple(Opcode.ASSIGN_FNR));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_FNR));
}
/** Pushes the current value of {@code FS} onto the operand stack. */
public void pushFS() {
- queue.add(new Tuple(Opcode.PUSH_FS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_FS));
}
/** Assigns the top-of-stack value to {@code FS}. */
public void assignFS() {
- queue.add(new Tuple(Opcode.ASSIGN_FS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_FS));
}
/** Pushes the current value of {@code RS} onto the operand stack. */
public void pushRS() {
- queue.add(new Tuple(Opcode.PUSH_RS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_RS));
}
/** Assigns the top-of-stack value to {@code RS}. */
public void assignRS() {
- queue.add(new Tuple(Opcode.ASSIGN_RS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_RS));
}
/** Pushes the current value of {@code OFS} onto the operand stack. */
public void pushOFS() {
- queue.add(new Tuple(Opcode.PUSH_OFS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_OFS));
}
/** Assigns the top-of-stack value to {@code OFS}. */
public void assignOFS() {
- queue.add(new Tuple(Opcode.ASSIGN_OFS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_OFS));
}
/** Pushes the current value of {@code ORS} onto the operand stack. */
public void pushORS() {
- queue.add(new Tuple(Opcode.PUSH_ORS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_ORS));
}
/** Assigns the top-of-stack value to {@code ORS}. */
public void assignORS() {
- queue.add(new Tuple(Opcode.ASSIGN_ORS));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_ORS));
}
/** Pushes the current value of {@code RSTART} onto the operand stack. */
public void pushRSTART() {
- queue.add(new Tuple(Opcode.PUSH_RSTART));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_RSTART));
}
/** Assigns the top-of-stack value to {@code RSTART}. */
public void assignRSTART() {
- queue.add(new Tuple(Opcode.ASSIGN_RSTART));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_RSTART));
}
/** Pushes the current value of {@code RLENGTH} onto the operand stack. */
public void pushRLENGTH() {
- queue.add(new Tuple(Opcode.PUSH_RLENGTH));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_RLENGTH));
}
/** Assigns the top-of-stack value to {@code RLENGTH}. */
public void assignRLENGTH() {
- queue.add(new Tuple(Opcode.ASSIGN_RLENGTH));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_RLENGTH));
}
/** Pushes the current value of {@code FILENAME} onto the operand stack. */
public void pushFILENAME() {
- queue.add(new Tuple(Opcode.PUSH_FILENAME));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_FILENAME));
}
/** Assigns the top-of-stack value to {@code FILENAME}. */
public void assignFILENAME() {
- queue.add(new Tuple(Opcode.ASSIGN_FILENAME));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_FILENAME));
}
/** Pushes the current value of {@code SUBSEP} onto the operand stack. */
public void pushSUBSEP() {
- queue.add(new Tuple(Opcode.PUSH_SUBSEP));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_SUBSEP));
}
/** Assigns the top-of-stack value to {@code SUBSEP}. */
public void assignSUBSEP() {
- queue.add(new Tuple(Opcode.ASSIGN_SUBSEP));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_SUBSEP));
}
/** Pushes the current value of {@code CONVFMT} onto the operand stack. */
public void pushCONVFMT() {
- queue.add(new Tuple(Opcode.PUSH_CONVFMT));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_CONVFMT));
}
/** Assigns the top-of-stack value to {@code CONVFMT}. */
public void assignCONVFMT() {
- queue.add(new Tuple(Opcode.ASSIGN_CONVFMT));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_CONVFMT));
}
/** Pushes the current value of {@code OFMT} onto the operand stack. */
public void pushOFMT() {
- queue.add(new Tuple(Opcode.PUSH_OFMT));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_OFMT));
}
/** Assigns the top-of-stack value to {@code OFMT}. */
public void assignOFMT() {
- queue.add(new Tuple(Opcode.ASSIGN_OFMT));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_OFMT));
}
/** Pushes the current value of {@code ARGC} onto the operand stack. */
public void pushARGC() {
- queue.add(new Tuple(Opcode.PUSH_ARGC));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.PUSH_ARGC));
}
/** Assigns the top-of-stack value to {@code ARGC}. */
public void assignARGC() {
- queue.add(new Tuple(Opcode.ASSIGN_ARGC));
+ queue.add(new Tuple.BuiltinVarTuple(Opcode.ASSIGN_ARGC));
}
/**
@@ -1519,7 +1519,7 @@ public void assignARGC() {
*
*/
public void applyRS() {
- queue.add(new Tuple(Opcode.APPLY_RS));
+ queue.add(new Tuple.NoOperandTuple(Opcode.APPLY_RS));
}
/**
@@ -1531,11 +1531,11 @@ public void applyRS() {
* @param numFormalParams a int
*/
public void function(String funcName, int numFormalParams) {
- queue.add(new Tuple(Opcode.FUNCTION, funcName, numFormalParams));
+ queue.add(new Tuple.FunctionTuple(funcName, numFormalParams));
}
// public void callFunction(Address addr, String funcName, int numFormalParams, int numActualParams) {
- // queue.add(new Tuple(Opcode.CALL_FUNCTION, addr, funcName, numFormalParams, numActualParams)); }
+ // queue.add(new Tuple.CallFunctionTuple(addr, funcName, numFormalParams, numActualParams)); }
/**
*
@@ -1552,7 +1552,7 @@ public void callFunction(
String funcName,
int numFormalParams,
int numActualParams) {
- queue.add(new Tuple(Opcode.CALL_FUNCTION, addressSupplier, funcName, numFormalParams, numActualParams));
+ queue.add(new Tuple.CallFunctionTuple(addressSupplier, funcName, numFormalParams, numActualParams));
}
/**
@@ -1561,7 +1561,7 @@ public void callFunction(
*
*/
public void setReturnResult() {
- queue.add(new Tuple(Opcode.SET_RETURN_RESULT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.SET_RETURN_RESULT));
}
/**
@@ -1570,7 +1570,7 @@ public void setReturnResult() {
*
*/
public void returnFromFunction() {
- queue.add(new Tuple(Opcode.RETURN_FROM_FUNCTION));
+ queue.add(new Tuple.NoOperandTuple(Opcode.RETURN_FROM_FUNCTION));
}
/**
@@ -1581,7 +1581,7 @@ public void returnFromFunction() {
* @param numGlobals a int
*/
public void setNumGlobals(int numGlobals) {
- queue.add(new Tuple(Opcode.SET_NUM_GLOBALS, numGlobals));
+ queue.add(new Tuple.CountTuple(Opcode.SET_NUM_GLOBALS, numGlobals));
}
/**
@@ -1590,7 +1590,7 @@ public void setNumGlobals(int numGlobals) {
*
*/
public void close() {
- queue.add(new Tuple(Opcode.CLOSE));
+ queue.add(new Tuple.NoOperandTuple(Opcode.CLOSE));
}
/**
@@ -1601,7 +1601,7 @@ public void close() {
* @param count a int
*/
public void applySubsep(int count) {
- queue.add(new Tuple(Opcode.APPLY_SUBSEP, count));
+ queue.add(new Tuple.CountTuple(Opcode.APPLY_SUBSEP, count));
}
/**
@@ -1613,14 +1613,14 @@ public void applySubsep(int count) {
* @param isGlobal a boolean
*/
public void deleteArrayElement(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DELETE_ARRAY_ELEMENT, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.DELETE_ARRAY_ELEMENT, offset, isGlobal));
}
/**
* Deletes a stack-provided associative-array element.
*/
public void deleteMapElement() {
- queue.add(new Tuple(Opcode.DELETE_MAP_ELEMENT));
+ queue.add(new Tuple.NoOperandTuple(Opcode.DELETE_MAP_ELEMENT));
}
/**
@@ -1632,7 +1632,7 @@ public void deleteMapElement() {
* @param isGlobal a boolean
*/
public void deleteArray(int offset, boolean isGlobal) {
- queue.add(new Tuple(Opcode.DELETE_ARRAY, offset, isGlobal));
+ queue.add(new Tuple.VariableTuple(Opcode.DELETE_ARRAY, offset, isGlobal));
}
/**
@@ -1643,7 +1643,7 @@ public void deleteArray(int offset, boolean isGlobal) {
* @param addr a {@link io.jawk.intermediate.Address} object
*/
public void setExitAddress(Address addr) {
- queue.add(new Tuple(Opcode.SET_EXIT_ADDRESS, addr));
+ queue.add(new Tuple.AddressTuple(Opcode.SET_EXIT_ADDRESS, addr));
}
/**
@@ -1654,7 +1654,7 @@ public void setExitAddress(Address addr) {
* @param b a boolean
*/
public void setWithinEndBlocks(boolean b) {
- queue.add(new Tuple(Opcode.SET_WITHIN_END_BLOCKS, b));
+ queue.add(new Tuple.BooleanTuple(Opcode.SET_WITHIN_END_BLOCKS, b));
}
/**
@@ -1663,7 +1663,7 @@ public void setWithinEndBlocks(boolean b) {
*
*/
public void exitWithCode() {
- queue.add(new Tuple(Opcode.EXIT_WITH_CODE));
+ queue.add(new Tuple.NoOperandTuple(Opcode.EXIT_WITH_CODE));
}
/**
@@ -1672,7 +1672,7 @@ public void exitWithCode() {
*
*/
public void exitWithoutCode() {
- queue.add(new Tuple(Opcode.EXIT_WITHOUT_CODE));
+ queue.add(new Tuple.NoOperandTuple(Opcode.EXIT_WITHOUT_CODE));
}
/**
@@ -1686,7 +1686,7 @@ public void regexp(String regexpStr) {
// For literal regexes (created by RegexpAst), precompile the Pattern
// and store it alongside the original string to skip runtime compilation.
Pattern precompiled = Pattern.compile(regexpStr);
- queue.add(new Tuple(Opcode.REGEXP, regexpStr, precompiled));
+ queue.add(new Tuple.RegexTuple(regexpStr, precompiled));
}
/**
@@ -1695,7 +1695,7 @@ public void regexp(String regexpStr) {
*
*/
public void conditionPair() {
- queue.add(new Tuple(Opcode.CONDITION_PAIR));
+ queue.add(new Tuple.NoOperandTuple(Opcode.CONDITION_PAIR));
}
/**
@@ -1704,14 +1704,14 @@ public void conditionPair() {
*
*/
public void isIn() {
- queue.add(new Tuple(Opcode.IS_IN));
+ queue.add(new Tuple.NoOperandTuple(Opcode.IS_IN));
}
/**
* Emits a tuple that pushes the current script context onto the stack.
*/
public void scriptThis() {
- queue.add(new Tuple(Opcode.THIS));
+ queue.add(new Tuple.NoOperandTuple(Opcode.THIS));
}
/**
@@ -1722,7 +1722,7 @@ public void scriptThis() {
* @param isInitial {@code true} when this tuple opens an extension call sequence
*/
public void extension(ExtensionFunction function, int paramCount, boolean isInitial) {
- queue.add(new Tuple(Opcode.EXTENSION, function, paramCount, isInitial));
+ queue.add(new Tuple.ExtensionTuple(function, paramCount, isInitial));
}
/**
@@ -1896,7 +1896,7 @@ private boolean peepholeOptimizePass() {
long fieldIndex = JRT.toLong(literal);
Tuple replacement = createGetInputFieldConst(
fieldIndex,
- tuple.getLineno());
+ tuple.getLineNumber());
optimizedQueue.add(replacement);
mapFoldedRange(indexMapping, oldIndex, 2, newIndex);
oldIndex += 2;
@@ -1912,7 +1912,7 @@ private boolean peepholeOptimizePass() {
if (secondLiteral != null) {
Object folded = foldBinary(literal, secondLiteral, opTuple);
if (folded != null) {
- Tuple replacement = createLiteralPush(folded, tuple.getLineno());
+ Tuple replacement = createLiteralPush(folded, tuple.getLineNumber());
optimizedQueue.add(replacement);
mapFoldedRange(indexMapping, oldIndex, 3, newIndex);
oldIndex += 3;
@@ -1926,7 +1926,7 @@ private boolean peepholeOptimizePass() {
Tuple opTuple = original.get(oldIndex + 1);
Object folded = foldUnary(literal, opTuple);
if (folded != null) {
- Tuple replacement = createLiteralPush(folded, tuple.getLineno());
+ Tuple replacement = createLiteralPush(folded, tuple.getLineNumber());
optimizedQueue.add(replacement);
mapFoldedRange(indexMapping, oldIndex, 2, newIndex);
oldIndex += 2;
@@ -1967,11 +1967,11 @@ private void mapFoldedRange(int[] indexMapping, int startIndex, int length, int
private Object literalValue(Tuple tuple) {
switch (tuple.getOpcode()) {
case PUSH_LONG:
- return Long.valueOf(tuple.getInts()[0]);
+ return Long.valueOf(((Tuple.PushLongTuple) tuple).getValue());
case PUSH_DOUBLE:
- return Double.valueOf(tuple.getDoubles()[0]);
+ return Double.valueOf(((Tuple.PushDoubleTuple) tuple).getValue());
case PUSH_STRING:
- return tuple.getStrings()[0];
+ return ((Tuple.PushStringTuple) tuple).getValue();
default:
return null;
}
@@ -2082,20 +2082,20 @@ private Object foldUnary(Object literal, Tuple operation) {
private Tuple createLiteralPush(Object value, int lineNumber) {
Tuple tuple;
if (value instanceof Long) {
- tuple = new Tuple(Opcode.PUSH_LONG, ((Long) value).longValue());
+ tuple = new Tuple.PushLongTuple(((Long) value).longValue());
} else if (value instanceof Integer) {
- tuple = new Tuple(Opcode.PUSH_LONG, ((Integer) value).longValue());
+ tuple = new Tuple.PushLongTuple(((Integer) value).longValue());
} else if (value instanceof Double) {
- tuple = new Tuple(Opcode.PUSH_DOUBLE, ((Double) value).doubleValue());
+ tuple = new Tuple.PushDoubleTuple(((Double) value).doubleValue());
} else if (value instanceof Number) {
double d = ((Number) value).doubleValue();
if (JRT.isActuallyLong(d)) {
- tuple = new Tuple(Opcode.PUSH_LONG, (long) Math.rint(d));
+ tuple = new Tuple.PushLongTuple((long) Math.rint(d));
} else {
- tuple = new Tuple(Opcode.PUSH_DOUBLE, d);
+ tuple = new Tuple.PushDoubleTuple(d);
}
} else if (value instanceof String) {
- tuple = new Tuple(Opcode.PUSH_STRING, (String) value);
+ tuple = new Tuple.PushStringTuple((String) value);
} else {
throw new IllegalArgumentException("Unsupported literal value: " + value);
}
@@ -2104,7 +2104,7 @@ private Tuple createLiteralPush(Object value, int lineNumber) {
}
private Tuple createGetInputFieldConst(long fieldIndex, int lineNumber) {
- Tuple tuple = new Tuple(Opcode.GET_INPUT_FIELD_CONST, fieldIndex);
+ Tuple tuple = new Tuple.InputFieldTuple(fieldIndex);
tuple.setLineNumber(lineNumber);
return tuple;
}
diff --git a/src/main/java/io/jawk/intermediate/PositionTracker.java b/src/main/java/io/jawk/intermediate/PositionTracker.java
index c588de0e..5227ab16 100644
--- a/src/main/java/io/jawk/intermediate/PositionTracker.java
+++ b/src/main/java/io/jawk/intermediate/PositionTracker.java
@@ -1,8 +1,6 @@
package io.jawk.intermediate;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import io.jawk.ext.ExtensionFunction;
-import java.util.regex.Pattern;
/*-
* ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
@@ -89,128 +87,13 @@ public Opcode opcode() {
return tuple.getOpcode();
}
- /**
- * Returns the long argument at the specified index without type dispatch.
- *
- * @param argIdx argument index
- * @return the long value
- */
- public long intArg(int argIdx) {
- return tuple.getInts()[argIdx];
- }
-
- /**
- * Returns the boolean argument at the specified index without type dispatch.
- *
- * @param argIdx argument index
- * @return the boolean value
- */
- public boolean boolArg(int argIdx) {
- return tuple.getBools()[argIdx];
- }
-
- /**
- * Returns the string argument at the specified index without type dispatch.
- *
- * @param argIdx argument index
- * @return the string value
- */
- public String stringArg(int argIdx) {
- return tuple.getStrings()[argIdx];
- }
-
- /**
- * Returns the double argument at the specified index without type dispatch.
- *
- * @param argIdx argument index
- * @return the double value
- */
- public double doubleArg(int argIdx) {
- return tuple.getDoubles()[argIdx];
- }
-
- /**
- * Returns the current tuple argument with runtime type dispatch.
- *
- * @param argIdx Argument index
- * @return Argument value as its boxed Java type
- */
- public Object arg(int argIdx) {
- Class> c = tuple.getTypes()[argIdx];
- if (c == Long.class) {
- return tuple.getInts()[argIdx];
- }
- if (c == Double.class) {
- return tuple.getDoubles()[argIdx];
- }
- if (c == String.class) {
- return tuple.getStrings()[argIdx];
- }
- if (c == Pattern.class) {
- return tuple.getPatterns()[argIdx];
- }
- if (c == Address.class) {
- return tuple.getAddress();
- }
- if (c == ExtensionFunction.class) {
- return tuple.getExtensionFunction();
- }
- throw new Error("Invalid arg type: " + c + ", arg_idx = " + argIdx + ", tuple = " + tuple);
- }
-
- /**
- * Returns the regular-expression argument at the supplied index.
- *
- * @param argIdx Argument index
- * @return Pattern argument
- */
- public Pattern patternArg(int argIdx) {
- if (tuple.getTypes()[argIdx] != Pattern.class) {
- throw new Error("Tuple does not contain a Pattern at index " + argIdx + ": " + tuple);
- }
- return tuple.getPatterns()[argIdx];
- }
-
- /**
- * Returns the extension-function argument stored on the current tuple.
- *
- * @return Extension function metadata
- */
- public ExtensionFunction extensionFunctionArg() {
- if (tuple.getTypes()[0] != ExtensionFunction.class) {
- throw new Error("Tuple does not contain an extension function: " + tuple);
- }
- return tuple.getExtensionFunction();
- }
-
- /**
- * Returns the tuple address argument, resolving lazy suppliers when needed.
- *
- * @return Current tuple address argument
- */
- public Address addressArg() {
- if (tuple.getAddress() == null) {
- tuple.setAddress(tuple.getAddressSupplier().get());
- }
- return tuple.getAddress();
- }
-
- /**
- * Returns the class argument stored on the current tuple.
- *
- * @return Class argument
- */
- public Class> classArg() {
- return tuple.getCls();
- }
-
/**
* Returns the source line number associated with the current tuple.
*
* @return Tuple source line number
*/
public int lineNumber() {
- return tuple.getLineno();
+ return tuple.getLineNumber();
}
/**
@@ -218,10 +101,20 @@ public int lineNumber() {
*
* @return Current queue index
*/
- public int current() {
+ public int currentIndex() {
return idx;
}
+ /**
+ * Returns the current typed tuple.
+ *
+ * @return current tuple
+ */
+ @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "PositionTracker exposes the current immutable instruction node for typed dispatch")
+ public Tuple current() {
+ return tuple;
+ }
+
/**
* Jumps directly to the tuple at the supplied queue index.
*
diff --git a/src/main/java/io/jawk/intermediate/Tuple.java b/src/main/java/io/jawk/intermediate/Tuple.java
index e6e08e14..94cd4640 100644
--- a/src/main/java/io/jawk/intermediate/Tuple.java
+++ b/src/main/java/io/jawk/intermediate/Tuple.java
@@ -23,259 +23,752 @@
*/
import java.io.Serializable;
-import java.util.regex.Pattern;
+import java.util.List;
import java.util.function.Supplier;
+import java.util.regex.Pattern;
import io.jawk.ext.ExtensionFunction;
/**
- * Represents a single opcode and its arguments within the tuple stream produced
- * by {@link AwkTuples}. While {@code AwkTuples} manages the list of tuples, this
- * class models one instruction and up to four typed operands.
- *
- * Some tuples defer resolution of a function address until the tuple list is
- * finalized; such tuples hold a {@link Supplier} that provides the
- * {@link Address} when needed.
+ * Represents one instruction in the tuple stream produced by {@link AwkTuples}.
+ * Concrete subclasses carry only the operands required by their opcode or opcode
+ * group.
*
* @author Danny Daglas
* @see AwkTuples
*/
-class Tuple implements Serializable {
+public abstract class Tuple implements Serializable {
private static final long serialVersionUID = 8105941219003992817L;
- private Opcode opcode;
- private long[] ints = new long[4];
- private boolean[] bools = new boolean[4];
- private double[] doubles = new double[4];
- private String[] strings = new String[4];
- private Pattern[] patterns = new Pattern[4];
- private Class>[] types = new Class[4];
- private Address address = null;
- private Class> cls = null;
- private transient Supplier
addressSupplier = null;
- private int lineno = -1;
+ private final Opcode opcode;
+ private int lineNumber = -1;
private Tuple next = null;
- private ExtensionFunction extensionFunction;
Tuple(Opcode opcode) {
this.opcode = opcode;
}
- Tuple(Opcode opcode, long i1) {
- this(opcode);
- ints[0] = i1;
- types[0] = Long.class;
+ /**
+ * Returns this tuple's opcode.
+ *
+ * @return opcode executed by the AVM
+ */
+ public final Opcode getOpcode() {
+ return opcode;
}
- Tuple(Opcode opcode, long i1, long i2) {
- this(opcode, i1);
- ints[1] = i2;
- types[1] = Long.class;
+ /**
+ * Returns this tuple's jump/call address, if it has one.
+ *
+ * @return tuple address, or {@code null}
+ */
+ public Address getAddress() {
+ return null;
+ }
+
+ /**
+ * Resolves deferred operands and validates resolved addresses.
+ *
+ * @param queue tuple queue used to validate address targets
+ */
+ public void touch(List queue) {
+ Address address = getAddress();
+ if (address == null) {
+ return;
+ }
+ if (address.index() == -1) {
+ throw new Error("address " + address + " is unresolved");
+ }
+ if (address.index() >= queue.size()) {
+ throw new Error("address " + address + " doesn't resolve to an actual list element");
+ }
}
- Tuple(Opcode opcode, long i1, boolean b2) {
- this(opcode, i1);
- bools[1] = b2;
- types[1] = Boolean.class;
+ boolean hasNext() {
+ return next != null;
}
- Tuple(Opcode opcode, long i1, boolean b2, boolean b3) {
- this(opcode, i1, b2);
- bools[2] = b3;
- types[2] = Boolean.class;
+ /**
+ * Returns the next tuple in execution order.
+ *
+ * @return next tuple, or {@code null} at the end of the stream
+ */
+ Tuple getNext() {
+ return next;
}
- Tuple(Opcode opcode, double d1) {
- this(opcode);
- doubles[0] = d1;
- types[0] = Double.class;
+ void setNext(Tuple next) {
+ this.next = next;
}
- Tuple(Opcode opcode, String s1) {
- this(opcode);
- strings[0] = s1;
- types[0] = String.class;
+ void setLineNumber(int lineNumber) {
+ this.lineNumber = lineNumber;
}
- Tuple(Opcode opcode, String s1, Pattern p2) {
- this(opcode, s1);
- patterns[1] = p2;
- types[1] = Pattern.class;
+ /**
+ * Returns the source line number associated with this tuple.
+ *
+ * @return source line number, or {@code -1} when unknown
+ */
+ public int getLineNumber() {
+ return lineNumber;
}
- Tuple(Opcode opcode, boolean b1) {
- this(opcode);
- bools[0] = b1;
- types[0] = Boolean.class;
+ private static String stringArgument(String value) {
+ return ", \"" + value + '"';
}
- Tuple(Opcode opcode, String s1, long i2) {
- this(opcode, s1);
- ints[1] = i2;
- types[1] = Long.class;
+ private static String patternArgument(Pattern pattern) {
+ return ", /" + (pattern == null ? "" : pattern.pattern()) + '/';
}
- Tuple(Opcode opcode, Address address) {
- this(opcode);
- this.address = address;
- types[0] = Address.class;
- }
+ /**
+ * Tuple for opcodes without operands.
+ */
+ public static class NoOperandTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+
+ NoOperandTuple(Opcode opcode) {
+ super(opcode);
+ }
- Tuple(Opcode opcode, String strarg, long intarg, boolean boolarg) {
- this(opcode, strarg, intarg);
- bools[2] = boolarg;
- types[2] = Boolean.class;
+ @Override
+ public String toString() {
+ return getOpcode().name();
+ }
}
- Tuple(Opcode opcode, ExtensionFunction function, long intarg, boolean boolarg) {
- this(opcode);
- this.extensionFunction = function;
- types[0] = ExtensionFunction.class;
- ints[1] = intarg;
- types[1] = Long.class;
- bools[2] = boolarg;
- types[2] = Boolean.class;
+ /**
+ * Tuple for JRT-managed built-in variable operations.
+ */
+ public static final class BuiltinVarTuple extends NoOperandTuple {
+ private static final long serialVersionUID = 1L;
+
+ BuiltinVarTuple(Opcode opcode) {
+ super(opcode);
+ }
}
- Tuple(Opcode opcode, Supplier addressSupplier, String s2, long i3, long i4) {
- this(opcode);
- this.addressSupplier = addressSupplier;
- strings[1] = s2;
- types[1] = String.class;
- ints[2] = i3;
- types[2] = Long.class;
- ints[3] = i4;
- types[3] = Long.class;
+ /**
+ * Tuple for a long literal.
+ */
+ public static final class PushLongTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final long value;
+
+ PushLongTuple(long value) {
+ super(Opcode.PUSH_LONG);
+ this.value = value;
+ }
+
+ /**
+ * Returns the literal value.
+ *
+ * @return literal long value
+ */
+ public long getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + value;
+ }
}
- Tuple(Opcode opcode, Class> cls) {
- this(opcode);
- this.cls = cls;
- types[0] = Class.class;
+ /**
+ * Tuple for a double literal.
+ */
+ public static final class PushDoubleTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final double value;
+
+ PushDoubleTuple(double value) {
+ super(Opcode.PUSH_DOUBLE);
+ this.value = value;
+ }
+
+ /**
+ * Returns the literal value.
+ *
+ * @return literal double value
+ */
+ public double getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + value;
+ }
}
- Tuple(Opcode opcode, String s1, String s2) {
- this(opcode, s1);
- strings[1] = s2;
- types[1] = String.class;
+ /**
+ * Tuple for a string literal.
+ */
+ public static final class PushStringTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final String value;
+
+ PushStringTuple(String value) {
+ super(Opcode.PUSH_STRING);
+ this.value = value;
+ }
+
+ /**
+ * Returns the literal value.
+ *
+ * @return literal string value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + stringArgument(value);
+ }
}
- boolean hasNext() {
- return next != null;
+ /**
+ * Tuple for opcodes whose single operand is a count.
+ */
+ public static class CountTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final long count;
+
+ CountTuple(Opcode opcode, long count) {
+ super(opcode);
+ this.count = count;
+ }
+
+ /**
+ * Returns the tuple count operand.
+ *
+ * @return count operand
+ */
+ public final long getCount() {
+ return count;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + count;
+ }
}
- Tuple getNext() {
- return next;
+ /**
+ * Tuple for print/printf redirection with an append flag.
+ */
+ public static final class CountAndAppendTuple extends CountTuple {
+ private static final long serialVersionUID = 1L;
+ private final boolean append;
+
+ CountAndAppendTuple(Opcode opcode, long count, boolean append) {
+ super(opcode, count);
+ this.append = append;
+ }
+
+ /**
+ * Indicates whether redirected output should append.
+ *
+ * @return {@code true} for append mode
+ */
+ public boolean isAppend() {
+ return append;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + getCount() + ", " + append;
+ }
}
- void setNext(Tuple next) {
- this.next = next;
+ /**
+ * Tuple for a long operand that is not interpreted by the tuple itself.
+ */
+ public static class LongTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final long value;
+
+ LongTuple(Opcode opcode, long value) {
+ super(opcode);
+ this.value = value;
+ }
+
+ /**
+ * Returns the long operand.
+ *
+ * @return long operand
+ */
+ public final long getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + value;
+ }
}
- void setLineNumber(int lineNumber) {
- this.lineno = lineNumber;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(opcode.name());
- int idx = 0;
- while ((idx < types.length) && (types[idx] != null)) {
- sb.append(", ");
- Class> type = types[idx];
- if (type == Long.class) {
- sb.append(ints[idx]);
- } else if (type == Boolean.class) {
- sb.append(bools[idx]);
- } else if (type == Double.class) {
- sb.append(doubles[idx]);
- } else if (type == String.class) {
- sb.append('"').append(strings[idx]).append('"');
- } else if (type == Pattern.class) {
- // Display regex patterns in /.../ form for readability
- Pattern p = patterns[idx];
- sb
- .append('/')
- .append(p == null ? "" : p.pattern())
- .append('/');
- } else if (type == Address.class) {
- sb.append(address);
- } else if (type == ExtensionFunction.class) {
- sb.append(extensionFunction.getKeyword());
- } else if (type == Class.class) {
- sb.append(cls);
- } else {
- throw new Error("Unknown param type (" + idx + "): " + type);
- }
- ++idx;
+ /**
+ * Tuple for a constant input-field index.
+ */
+ public static final class InputFieldTuple extends LongTuple {
+ private static final long serialVersionUID = 1L;
+
+ InputFieldTuple(long fieldIndex) {
+ super(Opcode.GET_INPUT_FIELD_CONST, fieldIndex);
+ }
+
+ /**
+ * Returns the constant input-field index.
+ *
+ * @return input-field index
+ */
+ public long getFieldIndex() {
+ return getValue();
}
- return sb.toString();
}
- public void touch(java.util.List queue) {
- if (addressSupplier != null) {
- address = addressSupplier.get();
- types[0] = Address.class;
+ /**
+ * Tuple for an address operand.
+ */
+ public static class AddressTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private Address address;
+
+ AddressTuple(Opcode opcode, Address address) {
+ super(opcode);
+ this.address = address;
}
- if (address != null) {
- if (address.index() == -1) {
- throw new Error("address " + address + " is unresolved");
- }
- if (address.index() >= queue.size()) {
- throw new Error("address " + address + " doesn't resolve to an actual list element");
- }
+
+ @Override
+ public Address getAddress() {
+ return address;
+ }
+
+ void setAddress(Address address) {
+ this.address = address;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + address;
}
}
- Opcode getOpcode() {
- return opcode;
+ /**
+ * Tuple for variable offset/global operands.
+ */
+ public static class VariableTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final long variableOffset;
+ private final boolean global;
+
+ VariableTuple(Opcode opcode, long variableOffset, boolean global) {
+ super(opcode);
+ this.variableOffset = variableOffset;
+ this.global = global;
+ }
+
+ /**
+ * Returns the variable offset.
+ *
+ * @return variable offset
+ */
+ public final long getVariableOffset() {
+ return variableOffset;
+ }
+
+ /**
+ * Indicates whether the variable offset belongs to the global frame.
+ *
+ * @return {@code true} for a global variable
+ */
+ public final boolean isGlobal() {
+ return global;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + variableOffset + ", " + global;
+ }
}
- long[] getInts() {
- return ints;
+ /**
+ * Tuple for scalar compound assignments.
+ */
+ public static final class CompoundAssignTuple extends VariableTuple {
+ private static final long serialVersionUID = 1L;
+
+ CompoundAssignTuple(Opcode opcode, long variableOffset, boolean global) {
+ super(opcode, variableOffset, global);
+ }
}
- boolean[] getBools() {
- return bools;
+ /**
+ * Tuple for array compound assignments.
+ */
+ public static final class CompoundAssignArrayTuple extends VariableTuple {
+ private static final long serialVersionUID = 1L;
+
+ CompoundAssignArrayTuple(Opcode opcode, long variableOffset, boolean global) {
+ super(opcode, variableOffset, global);
+ }
}
- double[] getDoubles() {
- return doubles;
+ /**
+ * Tuple for stack-provided map element compound assignments.
+ */
+ public static final class CompoundAssignMapElementTuple extends NoOperandTuple {
+ private static final long serialVersionUID = 1L;
+
+ CompoundAssignMapElementTuple(Opcode opcode) {
+ super(opcode);
+ }
}
- String[] getStrings() {
- return strings;
+ /**
+ * Tuple for input-field compound assignments.
+ */
+ public static final class CompoundAssignInputFieldTuple extends NoOperandTuple {
+ private static final long serialVersionUID = 1L;
+
+ CompoundAssignInputFieldTuple(Opcode opcode) {
+ super(opcode);
+ }
}
- Pattern[] getPatterns() {
- return patterns;
+ /**
+ * Tuple for variable dereference.
+ */
+ public static final class DereferenceTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final long variableOffset;
+ private final boolean array;
+ private final boolean global;
+
+ DereferenceTuple(long variableOffset, boolean array, boolean global) {
+ super(Opcode.DEREFERENCE);
+ this.variableOffset = variableOffset;
+ this.array = array;
+ this.global = global;
+ }
+
+ /**
+ * Returns the variable offset.
+ *
+ * @return variable offset
+ */
+ public long getVariableOffset() {
+ return variableOffset;
+ }
+
+ /**
+ * Indicates whether this dereference should initialize an array.
+ *
+ * @return {@code true} when the variable is an array
+ */
+ public boolean isArray() {
+ return array;
+ }
+
+ /**
+ * Indicates whether the variable offset belongs to the global frame.
+ *
+ * @return {@code true} for a global variable
+ */
+ public boolean isGlobal() {
+ return global;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + variableOffset + ", " + array + ", " + global;
+ }
}
- Class>[] getTypes() {
- return types;
+ /**
+ * Tuple for boolean operands.
+ */
+ public static final class BooleanTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final boolean value;
+
+ BooleanTuple(Opcode opcode, boolean value) {
+ super(opcode);
+ this.value = value;
+ }
+
+ /**
+ * Returns the boolean operand.
+ *
+ * @return boolean operand
+ */
+ public boolean getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + value;
+ }
}
- Address getAddress() {
- return address;
+ /**
+ * Tuple for sub/gsub against variable-backed values.
+ */
+ public static final class SubstitutionVariableTuple extends VariableTuple {
+ private static final long serialVersionUID = 1L;
+ private final boolean globalSubstitution;
+
+ SubstitutionVariableTuple(Opcode opcode, long variableOffset, boolean global, boolean globalSubstitution) {
+ super(opcode, variableOffset, global);
+ this.globalSubstitution = globalSubstitution;
+ }
+
+ /**
+ * Indicates whether this substitution is global.
+ *
+ * @return {@code true} for {@code gsub}, {@code false} for {@code sub}
+ */
+ public boolean isGlobalSubstitution() {
+ return globalSubstitution;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + getVariableOffset() + ", " + isGlobal() + ", " + globalSubstitution;
+ }
}
- Class> getCls() {
- return cls;
+ /**
+ * Tuple for a precompiled literal regular expression.
+ */
+ public static final class RegexTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final String regex;
+ private final Pattern pattern;
+
+ RegexTuple(String regex, Pattern pattern) {
+ super(Opcode.REGEXP);
+ this.regex = regex;
+ this.pattern = pattern;
+ }
+
+ /**
+ * Returns the original regular expression text.
+ *
+ * @return regular expression text
+ */
+ public String getRegex() {
+ return regex;
+ }
+
+ /**
+ * Returns the precompiled regular expression.
+ *
+ * @return compiled pattern
+ */
+ public Pattern getPattern() {
+ return pattern;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + stringArgument(regex) + patternArgument(pattern);
+ }
}
- Supplier getAddressSupplier() {
- return addressSupplier;
+ /**
+ * Tuple for a class check.
+ */
+ public static final class ClassTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final Class> type;
+
+ ClassTuple(Class> type) {
+ super(Opcode.CHECK_CLASS);
+ this.type = type;
+ }
+
+ /**
+ * Returns the required runtime type.
+ *
+ * @return required class
+ */
+ public Class> getType() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + type;
+ }
}
- ExtensionFunction getExtensionFunction() {
- return extensionFunction;
+ /**
+ * Tuple for function definitions.
+ */
+ public static final class FunctionTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final String functionName;
+ private final long numFormalParams;
+
+ FunctionTuple(String functionName, long numFormalParams) {
+ super(Opcode.FUNCTION);
+ this.functionName = functionName;
+ this.numFormalParams = numFormalParams;
+ }
+
+ /**
+ * Returns the function name.
+ *
+ * @return function name
+ */
+ public String getFunctionName() {
+ return functionName;
+ }
+
+ /**
+ * Returns the number of formal parameters.
+ *
+ * @return formal parameter count
+ */
+ public long getNumFormalParams() {
+ return numFormalParams;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + stringArgument(functionName) + ", " + numFormalParams;
+ }
}
- void setAddress(Address address) {
- this.address = address;
+ /**
+ * Tuple for function calls.
+ */
+ public static final class CallFunctionTuple extends AddressTuple {
+ private static final long serialVersionUID = 1L;
+ private transient Supplier addressSupplier;
+ private final String functionName;
+ private final long numFormalParams;
+ private final long numActualParams;
+
+ CallFunctionTuple(
+ Supplier addressSupplier,
+ String functionName,
+ long numFormalParams,
+ long numActualParams) {
+ super(Opcode.CALL_FUNCTION, null);
+ this.addressSupplier = addressSupplier;
+ this.functionName = functionName;
+ this.numFormalParams = numFormalParams;
+ this.numActualParams = numActualParams;
+ }
+
+ @Override
+ public Address getAddress() {
+ Address address = super.getAddress();
+ if (address == null && addressSupplier != null) {
+ address = addressSupplier.get();
+ setAddress(address);
+ }
+ return address;
+ }
+
+ @Override
+ public void touch(List queue) {
+ getAddress();
+ super.touch(queue);
+ }
+
+ /**
+ * Returns the function name.
+ *
+ * @return function name
+ */
+ public String getFunctionName() {
+ return functionName;
+ }
+
+ /**
+ * Returns the number of formal parameters.
+ *
+ * @return formal parameter count
+ */
+ public long getNumFormalParams() {
+ return numFormalParams;
+ }
+
+ /**
+ * Returns the number of actual parameters at this call site.
+ *
+ * @return actual parameter count
+ */
+ public long getNumActualParams() {
+ return numActualParams;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name()
+ + ", "
+ + getAddress()
+ + stringArgument(functionName)
+ + ", "
+ + numFormalParams
+ + ", "
+ + numActualParams;
+ }
}
- int getLineno() {
- return lineno;
+ /**
+ * Tuple for extension function invocations.
+ */
+ public static final class ExtensionTuple extends Tuple {
+ private static final long serialVersionUID = 1L;
+ private final ExtensionFunction function;
+ private final long argCount;
+ private final boolean initial;
+
+ ExtensionTuple(ExtensionFunction function, long argCount, boolean initial) {
+ super(Opcode.EXTENSION);
+ this.function = function;
+ this.argCount = argCount;
+ this.initial = initial;
+ }
+
+ /**
+ * Returns the extension function metadata.
+ *
+ * @return extension function
+ */
+ public ExtensionFunction getFunction() {
+ return function;
+ }
+
+ /**
+ * Returns the number of extension arguments.
+ *
+ * @return argument count
+ */
+ public long getArgCount() {
+ return argCount;
+ }
+
+ /**
+ * Indicates whether this tuple starts an extension call sequence.
+ *
+ * @return {@code true} for the initial extension call tuple
+ */
+ public boolean isInitial() {
+ return initial;
+ }
+
+ @Override
+ public String toString() {
+ return getOpcode().name() + ", " + function.getKeyword() + ", " + argCount + ", " + initial;
+ }
}
}
diff --git a/src/test/java/io/jawk/AwkTupleOptimizationTest.java b/src/test/java/io/jawk/AwkTupleOptimizationTest.java
index 5107a346..a10883ca 100644
--- a/src/test/java/io/jawk/AwkTupleOptimizationTest.java
+++ b/src/test/java/io/jawk/AwkTupleOptimizationTest.java
@@ -40,6 +40,11 @@
import io.jawk.intermediate.AwkTuples;
import io.jawk.intermediate.Opcode;
import io.jawk.intermediate.PositionTracker;
+import io.jawk.intermediate.Tuple;
+import io.jawk.intermediate.Tuple.AddressTuple;
+import io.jawk.intermediate.Tuple.PushDoubleTuple;
+import io.jawk.intermediate.Tuple.PushLongTuple;
+import io.jawk.intermediate.Tuple.PushStringTuple;
public class AwkTupleOptimizationTest {
@@ -208,7 +213,8 @@ public void retainsRecursiveFunctionBodies() throws Exception {
PositionTracker tracker = rawTuples(tuples).top();
while (!tracker.isEOF()) {
if (tracker.opcode() == Opcode.CALL_FUNCTION) {
- Address address = tracker.addressArg();
+ AddressTuple tuple = (AddressTuple) tracker.current();
+ Address address = tuple.getAddress();
assertTrue("Call target should be assigned", address.index() >= 0);
callTargets.add(Integer.valueOf(address.index()));
}
@@ -327,7 +333,8 @@ public void retargetsBranchesAwayFromPlaceholderTuples() throws Exception {
PositionTracker tracker = rawTuples(tuples).top();
while (!tracker.isEOF()) {
if (usesAddress(tracker.opcode())) {
- branchTargets.add(Integer.valueOf(tracker.addressArg().index()));
+ AddressTuple tuple = (AddressTuple) tracker.current();
+ branchTargets.add(Integer.valueOf(tuple.getAddress().index()));
}
tracker.next();
}
@@ -505,7 +512,7 @@ private static boolean hasLiteralPush(AwkProgram tuples, Object expected) {
if (opcode == Opcode.PUSH_LONG
|| opcode == Opcode.PUSH_DOUBLE
|| opcode == Opcode.PUSH_STRING) {
- Object value = tracker.arg(0);
+ Object value = literalValue(tracker.current());
if (expected instanceof Number && value instanceof Number) {
double actual = ((Number) value).doubleValue();
if (Double.compare(actual, ((Number) expected).doubleValue()) == 0) {
@@ -540,7 +547,7 @@ private static boolean usesAddress(Opcode opcode) {
private static Opcode opcodeAt(AwkProgram tuples, int index) {
PositionTracker tracker = rawTuples(tuples).top();
while (!tracker.isEOF()) {
- if (tracker.current() == index) {
+ if (tracker.currentIndex() == index) {
return tracker.opcode();
}
tracker.next();
@@ -548,6 +555,19 @@ private static Opcode opcodeAt(AwkProgram tuples, int index) {
throw new AssertionError("No tuple at index " + index);
}
+ private static Object literalValue(Tuple tuple) {
+ switch (tuple.getOpcode()) {
+ case PUSH_LONG:
+ return Long.valueOf(((PushLongTuple) tuple).getValue());
+ case PUSH_DOUBLE:
+ return Double.valueOf(((PushDoubleTuple) tuple).getValue());
+ case PUSH_STRING:
+ return ((PushStringTuple) tuple).getValue();
+ default:
+ throw new AssertionError("Tuple is not a literal push: " + tuple);
+ }
+ }
+
private static AwkTuples rawTuples(AwkProgram program) {
return (AwkTuples) program;
}
From fa457a51dc77f7b5acdbb14a618d5ace7acdf71a Mon Sep 17 00:00:00 2001
From: Bertrand Martin
Date: Mon, 11 May 2026 20:41:42 +0200
Subject: [PATCH 2/3] Drop resolved call-function address supplier
---
src/main/java/io/jawk/intermediate/Tuple.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/main/java/io/jawk/intermediate/Tuple.java b/src/main/java/io/jawk/intermediate/Tuple.java
index 94cd4640..d7de0443 100644
--- a/src/main/java/io/jawk/intermediate/Tuple.java
+++ b/src/main/java/io/jawk/intermediate/Tuple.java
@@ -673,6 +673,7 @@ public Address getAddress() {
if (address == null && addressSupplier != null) {
address = addressSupplier.get();
setAddress(address);
+ addressSupplier = null;
}
return address;
}
From 090df46e32a39d2cadde661977081986fdff1bc4 Mon Sep 17 00:00:00 2001
From: Bertrand Martin
Date: Mon, 11 May 2026 20:51:14 +0200
Subject: [PATCH 3/3] Refine tuple dispatch and clean up PR review comments
---
src/main/java/io/jawk/intermediate/AwkTuples.java | 3 ---
src/main/java/io/jawk/intermediate/PositionTracker.java | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/main/java/io/jawk/intermediate/AwkTuples.java b/src/main/java/io/jawk/intermediate/AwkTuples.java
index 65e641ea..a4f8ce0e 100644
--- a/src/main/java/io/jawk/intermediate/AwkTuples.java
+++ b/src/main/java/io/jawk/intermediate/AwkTuples.java
@@ -1534,9 +1534,6 @@ public void function(String funcName, int numFormalParams) {
queue.add(new Tuple.FunctionTuple(funcName, numFormalParams));
}
- // public void callFunction(Address addr, String funcName, int numFormalParams, int numActualParams) {
- // queue.add(new Tuple.CallFunctionTuple(addr, funcName, numFormalParams, numActualParams)); }
-
/**
*
* callFunction.
diff --git a/src/main/java/io/jawk/intermediate/PositionTracker.java b/src/main/java/io/jawk/intermediate/PositionTracker.java
index 5227ab16..5ab1e2f1 100644
--- a/src/main/java/io/jawk/intermediate/PositionTracker.java
+++ b/src/main/java/io/jawk/intermediate/PositionTracker.java
@@ -110,7 +110,7 @@ public int currentIndex() {
*
* @return current tuple
*/
- @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "PositionTracker exposes the current immutable instruction node for typed dispatch")
+ @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Tuple mutation is limited to package-internal stream construction and deferred address resolution")
public Tuple current() {
return tuple;
}