Python's comparison chains a < b < c are semantically (a < b) and (b < c) with b evaluated only once. The current parser handles a single comparison and treats any second one in a chain as a fresh comparison on the previous result ((a < b) < c), which parses to a well-formed tree but produces wrong semantics. Fix is in src/triton/parse.c::p_cmp: rather than emitting a single TN_NK_COMPARE binary, collect the chain of operands and operators and emit either a Compare node with N operands and N-1 ops packed in flags (and the corresponding lowering), or a chain of BoolOp(AND, ...) over individual comparisons with the middle operand re-used via a let-binding. The let-binding form is cleaner because it matches CPython's actual semantics including the single-evaluation rule.
Python's comparison chains
a < b < care semantically(a < b) and (b < c)with b evaluated only once. The current parser handles a single comparison and treats any second one in a chain as a fresh comparison on the previous result ((a < b) < c), which parses to a well-formed tree but produces wrong semantics. Fix is in src/triton/parse.c::p_cmp: rather than emitting a single TN_NK_COMPARE binary, collect the chain of operands and operators and emit either a Compare node with N operands and N-1 ops packed in flags (and the corresponding lowering), or a chain of BoolOp(AND, ...) over individual comparisons with the middle operand re-used via a let-binding. The let-binding form is cleaner because it matches CPython's actual semantics including the single-evaluation rule.