Como uma macro linguagem habilitada para manter o controle do código-fonte para depuração?

StackOverflow https://stackoverflow.com/questions/3214603

Pergunta

Este é um mais teórico pergunta sobre macros (eu acho).Eu sei macros obter o código-fonte e produzir código-objeto, sem a avaliação, permitindo aos programadores criar mais versátil estruturas sintáticas.Se eu tivesse que classificar estes dois sistemas de macro, eu diria que não foi o "C estilo de macro" e o "Lisp estilo de macro".

Parece que a depuração de macros pode ser um pouco complicado, porque em tempo de execução, o código que está na verdade executando difere do de origem.

Como o depurador de acompanhar a execução do programa em termos de pré-processado código-fonte?Há um especial "modo de depuração", que deve ser configurado para capturar dados extras sobre o macro?

Em C, eu posso entender que você gostaria de definir um tempo de compilação mudar para depuração, mas como uma linguagem interpretada, como algumas formas de Lisp, não é?

Pedir desculpas por não tentar este para fora, mas o lisp conjunto de ferramentas requer mais tempo do que eu para passar para descobrir.

Foi útil?

Solução

Eu não acho que há uma diferença fundamental no "estilo C" e "Lisp" estilo de macros em como eles são compilados.Ambos transformar a fonte antes de o compilador adequado vê-lo.A grande diferença é que C macros usar o pré-processador C (a mais fraca do idioma secundário é, sobretudo, para o simples seqüência de caracteres de substituição), enquanto Lisp macros são gravadas em Lisp em si (e, portanto, pode fazer qualquer coisa em tudo).

(Como um aparte:Eu não vi um não-compilado Lisp em quando ...certamente não desde a virada do século.Mas se qualquer coisa, ser interpretado parece fazer com que a macro problema depuração mais fácil, não é difícil, desde que você tenha mais informações.)

Concordo com Michael:Eu não vi um depurador para C que lida com macros em todos os.Código que usa macros são transformados antes de acontecer alguma coisa.O "debug mode" para compilar o código C em geral, apenas significa que ele lojas funções, tipos, variáveis, nomes de arquivos e tal - Eu não acho que qualquer um deles armazenar informações sobre macros.

  • Para depuração de programas que utilização macros, Lisp é praticamente o mesmo como C aqui:o depurador vê o código compilado, não a macro aplicação.Normalmente, as macros são mantido simples e depurado de forma independente antes de a utilizar, para evitar a necessidade desta, assim como C.

  • Para depurar macros - se, antes que você vá e usá-lo em algum lugar, Lisp não tem recursos que fazem isso mais fácil do que em C, por exemplo, o repl e macroexpand-1 (apesar de que no C há, obviamente, uma forma de macroexpand um arquivo inteiro, totalmente, em de uma vez).Você pode ver o antes-e-depois de um macroexpansion, direito em seu editor, quando você escrever isso.

Eu não consigo lembrar de qualquer momento deparei com uma situação onde a depuração em uma definição de macro em si teria sido útil.Ou é um bug na definição de macro, caso em que macroexpand-1 isola o problema imediatamente, ou é um bug abaixo, caso em que a depuração normal instalações funcionam bem e não me importo com o que um macroexpansion ocorreu entre dois quadros da minha pilha de chamadas.

Outras dicas

em lispworks os desenvolvedores podem usar o ferramenta de passo .

lispworks fornece um passo, onde se pode percorrer o completo processo de expansão macro .

Você deve realmente olhar para o tipo de suporte que raquete tem para depurar o código com macros. Este suporte tem dois aspectos, como Ken menciona. Por um lado, há a questão das macros de depuração: em comum, a melhor maneira de fazer isso é apenas expandir manualmente as formas de macro. Com o CPP, a situação é semelhante, mas mais primitiva - você executaria o código apenas através da expansão do CPP e inspecionará o resultado. No entanto, ambos são insuficientes para macros mais envolvidos, e esta foi a motivação para ter um macro Debugger Na raquete - Ele mostra as etapas de expansão de sintaxe uma por uma, com indicações adicionais baseadas na GUI para coisas como identificadores de ligação, etc.

No lado de Utilizar macros, a raquete sempre foi mais avançada do que outros esquemas e implementações lisp. A ideia é que cada expressão (como objeto sintático) é o código mais dados adicionais que contêm seu local de origem. Desta forma, quando um formulário é uma macro, o código expandido que tem peças provenientes da macro terá o local de origem correto - a partir da definição da macro em vez de de seu uso (onde os formulários não estão realmente presentes). Alguns esquemas e implementações LISP implementarão um limitado para isso usando a identidade de subformulações, como Dmitry-VK mencionado.

Eu não sei sobre macros lisp (que eu suspeito são provavelmente bem diferentes do que c de macros) ou depuração, mas muitos - provavelmente mais - os depuradores c / c ++ não lidam com a depuração de nível de origem de macros C, particularmente bem.

Geralmente, depuradores c / c ++ eles não "passo" para a definição de macro.Se uma macro se expande em várias instruções, o depurador geralmente ficará na mesma linha de origem (onde a macro é invocada) para cada operação de "etapa" do depurador.

Isso pode fazer a depuração de macros um pouco mais doloroso do que poderiam ser - mais uma razão para evitá-los em C / C ++.Se uma macro é mal comportada de maneira verdadeiramente misteriosa, eu vou cair no modo de montagem para depurar ou expandir a macro (manualmente ou usando o comutador do compilador).É muito raro que você tenha que ir a isso extremo;Se você está escrevendo macros que são tão complicados, provavelmente está tomando a abordagem errada.

Normalmente em depuração de nível de código C tem granularidade de linha ("próximo" comando) ou granularidade em nível de instrução ("passo em"). Os processadores de macro inserem diretivas especiais para a origem processada que permitem o compilador para mapear seqüências compiladas de instruções de CPU para linhas de código-fonte.

Não existe nenhuma convenção entre macros e compilador para rastrear o código-fonte para o mapeamento de código compilado, por isso nem sempre é possível fazer um único passo no código-fonte.

opção óbvia é fazer um único passo no código macroexpendido. O compilador já vê final, expandido, versão do código e pode rastrear o código-fonte para o mapeamento de código de máquina.

Outra opção é usar o fato de que expressões lisp durante a manipulação ter identidade. Se a macro é simples e apenas destruir e colar o código no modelo, algumas expressões de código expandido serão idênticas (em relação à comparação eq) para expressões que foram lidas do código-fonte. Nesse caso, o compilador pode mapear algumas expressões do código expandido para o código-fonte.

A resposta simples é que é complicado ;-) Existem várias coisas diferentes que contribuem para serem capazes de depurar um programa e ainda mais para rastrear macros.

em C e C ++, o pré-processador é usado para expandir macros e inclui o código-fonte real. Os nomes de arquivos e números de linha originários são rastreados neste arquivo de origem expandido usando diretivas #line.

http://msdn.microsoft.com/ pt-us / biblioteca / b5w2czay (vs.80) .aspx

Quando um programa C ou C ++ é compilado com depuração ativada, o montador gera informações adicionais no arquivo de objeto que rastreia linhas de origem, nomes de símbolos, digite descritores, etc.

http://sources.redhat.com/gdb/onlinedocs/stabs.html

O sistema operacional possui recursos que possibilitem que um depurador anexe a um processo e controle a execução do processo; pausando, único passo, etc.

Quando um depurador é conectado ao programa, ele traduz a pilha de processo e o contador de programas de volta em forma simbólica, observando o significado dos endereços do programa nas informações de depuração.

Idiomas dinâmicos normalmente executam em uma máquina virtual, seja um intérprete ou um VM bytecode. É a VM que fornece ganchos para permitir que um depurador controle o fluxo de programa e inspecione o estado do programa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top