summaryrefslogtreecommitdiffstats
path: root/Python/instruction_sequence.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/instruction_sequence.c')
-rw-r--r--Python/instruction_sequence.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/Python/instruction_sequence.c b/Python/instruction_sequence.c
index 597d2b7..d843d5f 100644
--- a/Python/instruction_sequence.c
+++ b/Python/instruction_sequence.c
@@ -141,6 +141,21 @@ _PyInstructionSequence_InsertInstruction(instr_sequence *seq, int pos,
return SUCCESS;
}
+int
+_PyInstructionSequence_AddNested(instr_sequence *seq, instr_sequence *nested)
+{
+ if (seq->s_nested == NULL) {
+ seq->s_nested = PyList_New(0);
+ if (seq->s_nested == NULL) {
+ return ERROR;
+ }
+ }
+ if (PyList_Append(seq->s_nested, (PyObject*)nested) < 0) {
+ return ERROR;
+ }
+ return SUCCESS;
+}
+
void
PyInstructionSequence_Fini(instr_sequence *seq) {
PyMem_Free(seq->s_labelmap);
@@ -149,3 +164,288 @@ PyInstructionSequence_Fini(instr_sequence *seq) {
PyMem_Free(seq->s_instrs);
seq->s_instrs = NULL;
}
+
+/*[clinic input]
+class InstructionSequenceType "_PyInstructionSequence *" "&_PyInstructionSequence_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=589963e07480390f]*/
+
+#include "clinic/instruction_sequence.c.h"
+
+static _PyInstructionSequence*
+inst_seq_create(void)
+{
+ _PyInstructionSequence *seq;
+ seq = PyObject_GC_New(_PyInstructionSequence, &_PyInstructionSequence_Type);
+ if (seq == NULL) {
+ return NULL;
+ }
+ seq->s_instrs = NULL;
+ seq->s_allocated = 0;
+ seq->s_used = 0;
+ seq->s_next_free_label = 0;
+ seq->s_labelmap = NULL;
+ seq->s_labelmap_size = 0;
+ seq->s_nested = NULL;
+
+ PyObject_GC_Track(seq);
+ return seq;
+}
+
+PyObject*
+_PyInstructionSequence_New(void)
+{
+ _PyInstructionSequence *seq = inst_seq_create();
+ if (seq == NULL) {
+ return NULL;
+ }
+ return (PyObject*)seq;
+}
+
+/*[clinic input]
+@classmethod
+InstructionSequenceType.__new__ as inst_seq_new
+
+Create a new InstructionSequence object.
+[clinic start generated code]*/
+
+static PyObject *
+inst_seq_new_impl(PyTypeObject *type)
+/*[clinic end generated code: output=98881de92c8876f6 input=b393150146849c74]*/
+{
+ return (PyObject*)inst_seq_create();
+}
+
+/*[clinic input]
+InstructionSequenceType.use_label
+
+ label: int
+
+Place label at current location.
+[clinic start generated code]*/
+
+static PyObject *
+InstructionSequenceType_use_label_impl(_PyInstructionSequence *self,
+ int label)
+/*[clinic end generated code: output=4c06bbacb2854755 input=da55f49bb91841f3]*/
+
+{
+ if (_PyInstructionSequence_UseLabel(self, label) < 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+InstructionSequenceType.addop
+
+ opcode: int
+ oparg: int
+ lineno: int
+ col_offset: int
+ end_lineno: int
+ end_col_offset: int
+
+Append an instruction.
+[clinic start generated code]*/
+
+static PyObject *
+InstructionSequenceType_addop_impl(_PyInstructionSequence *self, int opcode,
+ int oparg, int lineno, int col_offset,
+ int end_lineno, int end_col_offset)
+/*[clinic end generated code: output=af0cc22c048dfbf3 input=012762ac88198713]*/
+{
+ _Py_SourceLocation loc = {lineno, col_offset, end_lineno, end_col_offset};
+ if (_PyInstructionSequence_Addop(self, opcode, oparg, loc) < 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+InstructionSequenceType.new_label -> int
+
+Return a new label.
+[clinic start generated code]*/
+
+static int
+InstructionSequenceType_new_label_impl(_PyInstructionSequence *self)
+/*[clinic end generated code: output=dcb0589e4f5bf4bd input=c66040b9897bc327]*/
+{
+ _PyJumpTargetLabel lbl = _PyInstructionSequence_NewLabel(self);
+ return lbl.id;
+}
+
+/*[clinic input]
+InstructionSequenceType.add_nested
+
+ nested: object
+
+Add a nested sequence.
+[clinic start generated code]*/
+
+static PyObject *
+InstructionSequenceType_add_nested_impl(_PyInstructionSequence *self,
+ PyObject *nested)
+/*[clinic end generated code: output=14540fad459f7971 input=f2c482568b3b3c0f]*/
+{
+ if (!_PyInstructionSequence_Check(nested)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected an instruction sequence, not %T",
+ Py_TYPE(nested));
+ return NULL;
+ }
+ if (_PyInstructionSequence_AddNested(self, (_PyInstructionSequence*)nested) < 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+InstructionSequenceType.get_nested
+
+Add a nested sequence.
+[clinic start generated code]*/
+
+static PyObject *
+InstructionSequenceType_get_nested_impl(_PyInstructionSequence *self)
+/*[clinic end generated code: output=f415112c292630cb input=e429e474c57b95b4]*/
+{
+ if (self->s_nested == NULL) {
+ return PyList_New(0);
+ }
+ return Py_NewRef(self->s_nested);
+}
+
+/*[clinic input]
+InstructionSequenceType.get_instructions
+
+Return the instructions as a list of tuples or labels.
+[clinic start generated code]*/
+
+static PyObject *
+InstructionSequenceType_get_instructions_impl(_PyInstructionSequence *self)
+/*[clinic end generated code: output=23f4f3f894c301b3 input=fbadb5dadb611291]*/
+{
+ if (_PyInstructionSequence_ApplyLabelMap(self) < 0) {
+ return NULL;
+ }
+ PyObject *instructions = PyList_New(0);
+ if (instructions == NULL) {
+ return NULL;
+ }
+ for (int i = 0; i < self->s_used; i++) {
+ instruction *instr = &self->s_instrs[i];
+ location loc = instr->i_loc;
+ PyObject *inst_tuple;
+
+ if (OPCODE_HAS_ARG(instr->i_opcode)) {
+ inst_tuple = Py_BuildValue(
+ "(iiiiii)", instr->i_opcode, instr->i_oparg,
+ loc.lineno, loc.end_lineno,
+ loc.col_offset, loc.end_col_offset);
+ }
+ else {
+ inst_tuple = Py_BuildValue(
+ "(iOiiii)", instr->i_opcode, Py_None,
+ loc.lineno, loc.end_lineno,
+ loc.col_offset, loc.end_col_offset);
+ }
+ if (inst_tuple == NULL) {
+ goto error;
+ }
+
+ int res = PyList_Append(instructions, inst_tuple);
+ Py_DECREF(inst_tuple);
+ if (res != 0) {
+ goto error;
+ }
+ }
+ return instructions;
+error:
+ Py_XDECREF(instructions);
+ return NULL;
+}
+
+static PyMethodDef inst_seq_methods[] = {
+ INSTRUCTIONSEQUENCETYPE_ADDOP_METHODDEF
+ INSTRUCTIONSEQUENCETYPE_NEW_LABEL_METHODDEF
+ INSTRUCTIONSEQUENCETYPE_USE_LABEL_METHODDEF
+ INSTRUCTIONSEQUENCETYPE_ADD_NESTED_METHODDEF
+ INSTRUCTIONSEQUENCETYPE_GET_NESTED_METHODDEF
+ INSTRUCTIONSEQUENCETYPE_GET_INSTRUCTIONS_METHODDEF
+ {NULL, NULL, 0, NULL},
+};
+
+static PyMemberDef inst_seq_memberlist[] = {
+ {NULL} /* Sentinel */
+};
+
+static PyGetSetDef inst_seq_getsetters[] = {
+ {NULL} /* Sentinel */
+};
+
+static void
+inst_seq_dealloc(_PyInstructionSequence *seq)
+{
+ PyObject_GC_UnTrack(seq);
+ Py_TRASHCAN_BEGIN(seq, inst_seq_dealloc)
+ PyInstructionSequence_Fini(seq);
+ PyObject_GC_Del(seq);
+ Py_TRASHCAN_END
+}
+
+static int
+inst_seq_traverse(_PyInstructionSequence *seq, visitproc visit, void *arg)
+{
+ Py_VISIT(seq->s_nested);
+ return 0;
+}
+
+static int
+inst_seq_clear(_PyInstructionSequence *seq)
+{
+ Py_CLEAR(seq->s_nested);
+ return 0;
+}
+
+PyTypeObject _PyInstructionSequence_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "InstructionSequence",
+ sizeof(_PyInstructionSequence),
+ 0,
+ (destructor)inst_seq_dealloc, /*tp_dealloc*/
+ 0, /*tp_vectorcall_offset*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_as_async*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ inst_seq_new__doc__, /* tp_doc */
+ (traverseproc)inst_seq_traverse, /* tp_traverse */
+ (inquiry)inst_seq_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ inst_seq_methods, /* tp_methods */
+ inst_seq_memberlist, /* tp_members */
+ inst_seq_getsetters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ inst_seq_new, /* tp_new */
+};