From 409f17582779fc4792d20a7f9e0a8b2862f3b797 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Thu, 1 Jun 2023 13:55:17 -0700 Subject: [PATCH] Reduce code duplication for pre-3.11 binary ops, based on #348 --- ASTNode.cpp | 72 ++++- ASTNode.h | 12 +- ASTree.cpp | 260 ++---------------- ...BINARY_OP.3.11.pyc => binary_ops.3.11.pyc} | Bin tests/input/{BINARY_OP.py => binary_ops.py} | 2 +- .../{BINARY_OP.txt => binary_ops.txt} | 0 6 files changed, 101 insertions(+), 245 deletions(-) rename tests/compiled/{BINARY_OP.3.11.pyc => binary_ops.3.11.pyc} (100%) rename tests/input/{BINARY_OP.py => binary_ops.py} (94%) rename tests/tokenized/{BINARY_OP.txt => binary_ops.txt} (100%) diff --git a/ASTNode.cpp b/ASTNode.cpp index 8eb3cdd..6959d6a 100644 --- a/ASTNode.cpp +++ b/ASTNode.cpp @@ -1,4 +1,5 @@ #include "ASTNode.h" +#include "bytecode.h" /* ASTNodeList */ void ASTNodeList::removeLast() @@ -37,7 +38,71 @@ const char* ASTBinary::op_str() const return s_op_strings[op()]; } -ASTBinary::BinOp ASTBinary::getBinOpFromOperand(int operand) +ASTBinary::BinOp ASTBinary::from_opcode(int opcode) +{ + switch (opcode) { + case Pyc::BINARY_ADD: + return BIN_ADD; + case Pyc::BINARY_AND: + return BIN_AND; + case Pyc::BINARY_DIVIDE: + return BIN_DIVIDE; + case Pyc::BINARY_FLOOR_DIVIDE: + return BIN_FLOOR_DIVIDE; + case Pyc::BINARY_LSHIFT: + return BIN_LSHIFT; + case Pyc::BINARY_MODULO: + return BIN_MODULO; + case Pyc::BINARY_MULTIPLY: + return BIN_MULTIPLY; + case Pyc::BINARY_OR: + return BIN_OR; + case Pyc::BINARY_POWER: + return BIN_POWER; + case Pyc::BINARY_RSHIFT: + return BIN_RSHIFT; + case Pyc::BINARY_SUBTRACT: + return BIN_SUBTRACT; + case Pyc::BINARY_TRUE_DIVIDE: + return BIN_DIVIDE; + case Pyc::BINARY_XOR: + return BIN_XOR; + case Pyc::BINARY_MATRIX_MULTIPLY: + return BIN_MAT_MULTIPLY; + case Pyc::INPLACE_ADD: + return BIN_IP_ADD; + case Pyc::INPLACE_AND: + return BIN_IP_AND; + case Pyc::INPLACE_DIVIDE: + return BIN_IP_DIVIDE; + case Pyc::INPLACE_FLOOR_DIVIDE: + return BIN_IP_FLOOR_DIVIDE; + case Pyc::INPLACE_LSHIFT: + return BIN_IP_LSHIFT; + case Pyc::INPLACE_MODULO: + return BIN_IP_MODULO; + case Pyc::INPLACE_MULTIPLY: + return BIN_IP_MULTIPLY; + case Pyc::INPLACE_OR: + return BIN_IP_OR; + case Pyc::INPLACE_POWER: + return BIN_IP_POWER; + case Pyc::INPLACE_RSHIFT: + return BIN_IP_RSHIFT; + case Pyc::INPLACE_SUBTRACT: + return BIN_IP_SUBTRACT; + case Pyc::INPLACE_TRUE_DIVIDE: + return BIN_IP_DIVIDE; + case Pyc::INPLACE_XOR: + return BIN_IP_XOR; + case Pyc::INPLACE_MATRIX_MULTIPLY: + return BIN_IP_MAT_MULTIPLY; + default: + return BIN_INVALID; + } +} + +ASTBinary::BinOp ASTBinary::from_binary_op(int operand) { switch (operand) { case 0: @@ -45,7 +110,7 @@ ASTBinary::BinOp ASTBinary::getBinOpFromOperand(int operand) case 1: return BIN_AND; case 2: - return BIN_FLOOR; + return BIN_FLOOR_DIVIDE; case 3: return BIN_LSHIFT; case 4: @@ -71,7 +136,7 @@ ASTBinary::BinOp ASTBinary::getBinOpFromOperand(int operand) case 14: return BIN_IP_AND; case 15: - return BIN_IP_FLOOR; + return BIN_IP_FLOOR_DIVIDE; case 16: return BIN_IP_LSHIFT; case 17: @@ -97,6 +162,7 @@ ASTBinary::BinOp ASTBinary::getBinOpFromOperand(int operand) } } + /* ASTCompare */ const char* ASTCompare::op_str() const { diff --git a/ASTNode.h b/ASTNode.h index 29e6a94..9a621b0 100644 --- a/ASTNode.h +++ b/ASTNode.h @@ -129,13 +129,13 @@ private: class ASTBinary : public ASTNode { public: enum BinOp { - BIN_ATTR, BIN_POWER, BIN_MULTIPLY, BIN_DIVIDE, BIN_FLOOR, BIN_MODULO, - BIN_ADD, BIN_SUBTRACT, BIN_LSHIFT, BIN_RSHIFT, BIN_AND, BIN_XOR, - BIN_OR, BIN_LOG_AND, BIN_LOG_OR, BIN_MAT_MULTIPLY, + BIN_ATTR, BIN_POWER, BIN_MULTIPLY, BIN_DIVIDE, BIN_FLOOR_DIVIDE, + BIN_MODULO, BIN_ADD, BIN_SUBTRACT, BIN_LSHIFT, BIN_RSHIFT, BIN_AND, + BIN_XOR, BIN_OR, BIN_LOG_AND, BIN_LOG_OR, BIN_MAT_MULTIPLY, /* Inplace operations */ BIN_IP_ADD, BIN_IP_SUBTRACT, BIN_IP_MULTIPLY, BIN_IP_DIVIDE, BIN_IP_MODULO, BIN_IP_POWER, BIN_IP_LSHIFT, BIN_IP_RSHIFT, BIN_IP_AND, - BIN_IP_XOR, BIN_IP_OR, BIN_IP_FLOOR, BIN_IP_MAT_MULTIPLY, + BIN_IP_XOR, BIN_IP_OR, BIN_IP_FLOOR_DIVIDE, BIN_IP_MAT_MULTIPLY, /* Error Case */ BIN_INVALID }; @@ -149,7 +149,9 @@ public: int op() const { return m_op; } bool is_inplace() const { return m_op >= BIN_IP_ADD; } virtual const char* op_str() const; - static BinOp getBinOpFromOperand(int operand); + + static BinOp from_opcode(int opcode); + static BinOp from_binary_op(int operand); protected: int m_op; diff --git a/ASTree.cpp b/ASTree.cpp index a1eb341..bcf7996 100644 --- a/ASTree.cpp +++ b/ASTree.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "ASTree.h" #include "FastStack.h" #include "pyc_numeric.h" @@ -159,7 +160,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) switch (opcode) { case Pyc::BINARY_OP_A: { - ASTBinary::BinOp op = ASTBinary::getBinOpFromOperand(operand); + ASTBinary::BinOp op = ASTBinary::from_binary_op(operand); if (op == ASTBinary::BIN_INVALID) fprintf(stderr, "Unsupported `BINARY_OP` operand value: %d\n", operand); PycRef right = stack.top(); @@ -170,93 +171,42 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) } break; case Pyc::BINARY_ADD: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_ADD)); - } - break; case Pyc::BINARY_AND: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_AND)); - } - break; case Pyc::BINARY_DIVIDE: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_DIVIDE)); - } - break; case Pyc::BINARY_FLOOR_DIVIDE: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_FLOOR)); - } - break; case Pyc::BINARY_LSHIFT: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_LSHIFT)); - } - break; case Pyc::BINARY_MODULO: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_MODULO)); - } - break; case Pyc::BINARY_MULTIPLY: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_MULTIPLY)); - } - break; case Pyc::BINARY_OR: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_OR)); - } - break; case Pyc::BINARY_POWER: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_POWER)); - } - break; case Pyc::BINARY_RSHIFT: + case Pyc::BINARY_SUBTRACT: + case Pyc::BINARY_TRUE_DIVIDE: + case Pyc::BINARY_XOR: + case Pyc::BINARY_MATRIX_MULTIPLY: + case Pyc::INPLACE_ADD: + case Pyc::INPLACE_AND: + case Pyc::INPLACE_DIVIDE: + case Pyc::INPLACE_FLOOR_DIVIDE: + case Pyc::INPLACE_LSHIFT: + case Pyc::INPLACE_MODULO: + case Pyc::INPLACE_MULTIPLY: + case Pyc::INPLACE_OR: + case Pyc::INPLACE_POWER: + case Pyc::INPLACE_RSHIFT: + case Pyc::INPLACE_SUBTRACT: + case Pyc::INPLACE_TRUE_DIVIDE: + case Pyc::INPLACE_XOR: + case Pyc::INPLACE_MATRIX_MULTIPLY: { + ASTBinary::BinOp op = ASTBinary::from_opcode(opcode); + if (op == ASTBinary::BIN_INVALID) + throw std::runtime_error("Unhandled opcode from ASTBinary::from_opcode"); PycRef right = stack.top(); stack.pop(); PycRef left = stack.top(); stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_RSHIFT)); + stack.push(new ASTBinary(left, right, op)); } break; case Pyc::BINARY_SUBSCR: @@ -268,42 +218,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) stack.push(new ASTSubscr(src, subscr)); } break; - case Pyc::BINARY_SUBTRACT: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_SUBTRACT)); - } - break; - case Pyc::BINARY_TRUE_DIVIDE: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_DIVIDE)); - } - break; - case Pyc::BINARY_XOR: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_XOR)); - } - break; - case Pyc::BINARY_MATRIX_MULTIPLY: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_MAT_MULTIPLY)); - } - break; case Pyc::BREAK_LOOP: curblock->append(new ASTKeyword(ASTKeyword::KW_BREAK)); break; @@ -1074,132 +988,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) curblock->append(new ASTStore(import, NULL)); } break; - case Pyc::INPLACE_ADD: - { - PycRef right = stack.top(); - stack.pop(); - PycRef src = stack.top(); - stack.pop(); - stack.push(new ASTBinary(src, right, ASTBinary::BIN_IP_ADD)); - } - break; - case Pyc::INPLACE_AND: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_AND)); - } - break; - case Pyc::INPLACE_DIVIDE: - { - PycRef right = stack.top(); - stack.pop(); - PycRef src = stack.top(); - stack.pop(); - stack.push(new ASTBinary(src, right, ASTBinary::BIN_IP_DIVIDE)); - } - break; - case Pyc::INPLACE_FLOOR_DIVIDE: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_FLOOR)); - } - break; - case Pyc::INPLACE_LSHIFT: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_LSHIFT)); - } - break; - case Pyc::INPLACE_MODULO: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_MODULO)); - } - break; - case Pyc::INPLACE_MULTIPLY: - { - PycRef right = stack.top(); - stack.pop(); - PycRef src = stack.top(); - stack.pop(); - stack.push(new ASTBinary(src, right, ASTBinary::BIN_IP_MULTIPLY)); - } - break; - case Pyc::INPLACE_OR: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_OR)); - } - break; - case Pyc::INPLACE_POWER: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_POWER)); - } - break; - case Pyc::INPLACE_RSHIFT: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_RSHIFT)); - } - break; - case Pyc::INPLACE_SUBTRACT: - { - PycRef right = stack.top(); - stack.pop(); - PycRef src = stack.top(); - stack.pop(); - stack.push(new ASTBinary(src, right, ASTBinary::BIN_IP_SUBTRACT)); - } - break; - case Pyc::INPLACE_TRUE_DIVIDE: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_DIVIDE)); - } - break; - case Pyc::INPLACE_XOR: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_XOR)); - } - break; - case Pyc::INPLACE_MATRIX_MULTIPLY: - { - PycRef right = stack.top(); - stack.pop(); - PycRef left = stack.top(); - stack.pop(); - stack.push(new ASTBinary(left, right, ASTBinary::BIN_IP_MAT_MULTIPLY)); - } - break; case Pyc::IS_OP_A: { PycRef right = stack.top(); diff --git a/tests/compiled/BINARY_OP.3.11.pyc b/tests/compiled/binary_ops.3.11.pyc similarity index 100% rename from tests/compiled/BINARY_OP.3.11.pyc rename to tests/compiled/binary_ops.3.11.pyc diff --git a/tests/input/BINARY_OP.py b/tests/input/binary_ops.py similarity index 94% rename from tests/input/BINARY_OP.py rename to tests/input/binary_ops.py index 9a1dfa8..845b203 100644 --- a/tests/input/BINARY_OP.py +++ b/tests/input/binary_ops.py @@ -22,4 +22,4 @@ print('Bitwise right shift:', a >> b) print('Membership in:', a in b) print('Membership not in:', a not in b) print('Identity equality:', a is b) -print('Identity inequality:', a is not b) \ No newline at end of file +print('Identity inequality:', a is not b) diff --git a/tests/tokenized/BINARY_OP.txt b/tests/tokenized/binary_ops.txt similarity index 100% rename from tests/tokenized/BINARY_OP.txt rename to tests/tokenized/binary_ops.txt