Sim, o troff é Turing completo. Ele suporta recursão arbitrária e ramificação condicional, o que é suficiente. Ele também possui registradores e várias outras maneiras de armazenar dados, o que fornece outro caminho novamente.
A completude de Turing não implica que programas altamente complexos sejam práticos - apenas que eles são teoricamente possíveis, de alguma forma, em algum nível de remoção - e nem sua ausência implica que não sejam, de modo que nem o troff é Turing-complete nem o a ausência de programas complexos não sugere nada de um jeito ou de outro sobre isso.
Turing completude não é, geralmente, uma propriedade que significa algo útil para você, usuário. Tudo o que isso significa é que você pode simular uma máquina de Turing com ela, não que você queira, e não que a saída que você obteria seja algo parecido com o que você esperaria ler. A entrada ou saída pode ser apenas um número, ou mesmo o número de vezes que algo aparece, em vez de algo útil, e os tipos de máquina que você acaba simulando e seus programas geralmente são pouco compreensíveis para começar.
Muitas línguas e sistemas são Turing-complete aliás, mas não razoavelmente aplicável para qualquer tipo de programação real em que subconjunto (por exemplo, o jogo de Conway da vida ou CSS), e algumas línguas que são úteis para a programação real não são Turing completo (por exemplo, Agda). As características definidoras são realmente que você pode
- continue indo para sempre
- lembre-se da quantidade de dados que desejar
- escolha o que fazer, se houver, a seguir
Frequentemente, essas propriedades - principalmente a não rescisão - são realmente indesejáveis, possivelmente incluindo troff. Fora da ciência da computação teórica e do design da linguagem, a integridade de Turing não é uma propriedade muito interessante praticamente da época, apesar de cativante.
mov
instrução é Turing completo. (Devido aos modos de endereçamento que permitem usar tabelas de pesquisa, o mesmo mnemônico é usado para carregar, armazenar e mover imediatamente para registrar.) Em muitos outros ISAs que possuemmov
instruções (por exemplo, ARM), é apenas uma mudança reg-reg e não está completo. (Embora no ARM ele possa alternar / girar.) Além disso, você realmente precisajmp
criar um loop em torno do seu bloco demov
instruções, a menos que esteja no modo de 16 bits em que o ponteiro da instrução possa envolver um segmento de código de 64k para loop implicitamente.push {r4, lr}
/pop {r4,pc}
é comum em funções que precisam salvar / restaurar um registro preservado de chamada e manter a pilha alinhada: eles também salvam o registro de link e o colocam de volta no contador do programa para retornar. (As instruções de armazenamento / carregamento múltiplo do ARM de 32 bits usam um campo de bits para indicar quais registros armazenar / carregar.) E sim, você pode usar o PC como destino de umamov
ou de qualquer instrução. Eu não sabia que isso era comum no passado. Mas eu tinha ouvido falar de ISAs acionados por transporte.