diff --git a/src/main/java/io/jawk/backend/AVM.java b/src/main/java/io/jawk/backend/AVM.java index d84a815..9897f38 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,12 +1531,9 @@ 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)); } - /** ** callFunction. @@ -1552,7 +1549,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 +1558,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 +1567,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 +1578,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 +1587,7 @@ public void setNumGlobals(int numGlobals) { * */ public void close() { - queue.add(new Tuple(Opcode.CLOSE)); + queue.add(new Tuple.NoOperandTuple(Opcode.CLOSE)); } /** @@ -1601,7 +1598,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 +1610,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 +1629,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 +1640,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 +1651,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 +1660,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 +1669,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 +1683,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 +1692,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 +1701,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 +1719,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 +1893,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 +1909,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 +1923,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 +1964,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 +2079,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 +2101,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 c588de0..5ab1e2f 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 = "Tuple mutation is limited to package-internal stream construction and deferred address resolution") + 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 e6e08e1..d7de044 100644 --- a/src/main/java/io/jawk/intermediate/Tuple.java +++ b/src/main/java/io/jawk/intermediate/Tuple.java @@ -23,259 +23,753 @@ */ 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