split up `type_binop` so we can recursively call it without having to transform back to AST