honestly speaking, I think that shifts would almost always be better represented with functions, like lsl(a, 4), which solves the shenanigan between arithmetic/logic shift too.
slct(var, 6, 2) = expr; // var = (var &~ (0b111111 << 2)) | ((expr & 0b111111) << 2);
var = slct(expr, 6, 2); // var = (expr >> 2) & 0b111111;
Freaking BCPL had those in 1976, and that language was more primitive than C (it didn't even have any types beyond "machine word, reinterpreted accordingly to the operation applied to it").