0%
Pular para o conteúdo principal
0%

5.4

5.4 O Avaliador de Controle Explícito

Na seção 5.1 vimos como transformar programas JavaScript simples em descrições de máquinas de registradores. Agora vamos realizar essa transformação em um programa mais complexo, o avaliador metacircular das seções 4.1–4.4, que mostra como o comportamento de um interpretador JavaScript pode ser descrito em termos das funções evaluate e apply. O avaliador de controle explícito que desenvolvemos nesta seção mostra como os mecanismos subjacentes de chamada de função e passagem de argumentos usados no processo de avaliação podem ser descritos em termos de operações em registradores e pilhas. Além disso, o avaliador de controle explícito pode servir como uma implementação de um interpretador JavaScript, escrito em uma linguagem muito similar à linguagem de máquina nativa de computadores convencionais. O avaliador pode ser executado pelo simulador de máquina de registradores da seção 5.2. Alternativamente, pode ser usado como ponto de partida para construir uma implementação em linguagem de máquina de um avaliador JavaScript, ou até mesmo uma máquina de propósito especial para avaliar programas JavaScript. A Figura 5.16 mostra tal implementação em hardware: um chip de silício que atua como um avaliador para Scheme, a linguagem usada no lugar de JavaScript na edição original deste livro. Os projetistas do chip começaram com as especificações de caminho de dados e controlador para uma máquina de registradores similar ao avaliador descrito nesta seção e usaram programas de automação de design para construir o layout do circuito integrado.1

Figura 5.16: Uma implementação em chip de silício de um avaliador para Scheme.

Registradores e operações

Ao projetar o avaliador de controle explícito, devemos especificar as operações a serem usadas em nossa máquina de registradores. Descrevemos o avaliador metacircular em termos de sintaxe abstrata, usando funções como is_literal e make_function. Ao implementar a máquina de registradores, poderíamos expandir essas funções em sequências de operações elementares de memória de estrutura de lista, e implementar essas operações em nossa máquina de registradores. No entanto, isso tornaria nosso avaliador muito longo, obscurecendo a estrutura básica com detalhes. Para clarificar a apresentação, incluiremos como operações primitivas da máquina de registradores as funções de sintaxe dadas na seção 4.1.2 e as funções para representar ambientes e outros dados de tempo de execução dados nas seções 4.1.3 e 4.1.4. Para especificar completamente um avaliador que pudesse ser programado em uma linguagem de máquina de baixo nível ou implementado em hardware, substituiríamos essas operações por operações mais elementares, usando a implementação de estrutura de lista que descrevemos na seção 5.3.

Nossa máquina de registradores do avaliador JavaScript inclui uma pilha e sete registradores: comp, env, val, continue, fun, argl e unev. O registrador comp é usado para armazenar o componente a ser avaliado, e env contém o ambiente no qual a avaliação deve ser realizada. No final de uma avaliação, val contém o valor obtido pela avaliação do componente no ambiente designado. O registrador continue é usado para implementar recursão, como explicado na seção 5.1.4. (O avaliador precisa chamar a si mesmo recursivamente, já que avaliar um componente requer avaliar seus subcomponentes.) Os registradores fun, argl e unev são usados na avaliação de aplicações de função.

Não forneceremos um diagrama de caminho de dados para mostrar como os registradores e operações do avaliador estão conectados, nem daremos a lista completa de operações da máquina. Essas estão implícitas no controlador do avaliador, que será apresentado em detalhe.

Footnotes

  1. Veja Batali et al. 1982 para mais informações sobre o chip e o método pelo qual foi projetado.