antirez/picol: Um interpretador Tcl em 500 linhas de código

PUBLICIDADE

antirez/picol: Um interpretador Tcl em 500 linhas de código

Picol é um interpretador semelhante ao Tcl em 500 linhas de código que lancei em 15 de março de 2007. Recentemente olhei o código-fonte e percebi que este era um exemplo de programação C melhor comparado ao que eu lembrava, então estou colocando isso no GitHub para arquivá-lo, junto com os pontos principais do artigo original.

Quando construí este código, tinha algumas regras em mente:

  • Eu queria usar mais ou menos meu estilo C normal. No Picol você encontrará espaçamento C normal e até comentários.
  • Eu queria escrever um intérprete com um design semelhante ao real. Uma das poucas coisas úteis que você pode fazer com o Picol é aprender como escrever um interpretador Tcl se você for um programador novato, eu acho, então o objetivo era escrever um programa simples de entender, não apenas um curto programa.
  • O interpretador resultante deveria ser capaz de executar algum tipo de programa não trivial: apenas definir alguns vars e imprimir hello world não era uma opção.

O intérprete resultante: Picol

O analisador é muito semelhante ao Tcl, o Picol também suporta interpolação, por exemplo você pode escrever:

set a "pu"
set b {ts}
$a$b "Hello World!"

Observe que o Picol possui um shell interativo! então basta iniciá-lo sem argumentos para começar a jogar (para compilar o código use gcc -O2 -Wall -o picol picol.c).

Para executar um programa armazenado em um arquivo, use: picol filename.tcl.

Provavelmente o analisador poderia ser reescrito para ocupar menos espaço, atualmente são necessárias quase 250 linhas de código: isso é demais e deixa pouco espaço para todo o resto. Por outro lado, é um exemplo decente de como escrever analisadores manualmente.

Uma lista bruta dos recursos suportados:

  • Interpolação, como visto acima. Você também pode escrever "2+2 = [+ 2 2]" ou "My name is: $foobar".
  • Procedimentos, com retorno. Assim como o Tcl, se o retorno estiver faltando, o resultado do último comando executado será retornado.
  • If, if .. else .., while com break e continue.
  • Recursão.
  • Variáveis ​​dentro de procedimentos têm escopo limitado como Tcl, ou seja, existem call frames reais no Picol.
  • Os seguintes outros comandos: set + - * / == != > < >= <= puts.

Este é um exemplo de programas que o Picol pode executar:

proc fib {x} {
    if {== $x 0} {
        return 0
    }
    if {== $x 1} {
        return 1
    }
    return [+ [fib [- $x 1]] [fib [- $x 2]]]
}

puts [fib 20]
that of course will output fib(20). Another example:
proc square {x} {
    * $x $x
}

Ou:

set a 1
while {<= $a 10} {
    if {== $a 5} {
        puts {Missing five!}
        set a [+ $a 1]
        continue
    }
    puts "I can compute that $a*$a = [square $a]"
    set a [+ $a 1]
}
  • É bastante simples, a primeira parte importante que você vê no código-fonte é um analisador escrito à mão. A principal função do analisador é picolGetToken que apenas chama funções capazes de analisar as diferentes partes de um programa Tcl e retornar na estrutura de análise o tipo do token e os ponteiros de início/fim para extraí-lo.

Esta função de análise é, por sua vez, usada por picolEval para executar o programa. Cada token é usado para formar um novo argumento se um token separador foi encontrado antes, ou concatenado ao último argumento (é assim que a interpolação é realizada no Picol). Assim que um token EOL (fim de linha) for retornado, picolEval chamará o comando procurando-o em uma lista vinculada de comandos armazenados dentro da estrutura do interpretador.

A substituição de variáveis ​​e comandos é realizada por picolEval em si. O analisador é capaz de retornar tokens de variáveis ​​e comandos já removidos por $ e []então tudo o que é necessário fazer é procurar a variável no quadro de chamada e substituir o valor pelo token ou chamar recursivamente picolEval se for uma substituição de comando, usando o resultado em vez do token original.

Os comandos são descritos por um nome e um ponteiro para uma função C que implementa o comando. Na estrutura de comando há também um ponteiro de void de dados privados usado para armazenar dados privados do comando. Isso permite implementar vários comandos Picol usando uma única função C. Os procedimentos definidos pelo usuário são como comandos, mas são implementados passando como dados privados a lista de argumentos e o corpo do procedimento, portanto, uma única função C é capaz de implementar todos os procedimentos existentes definidos pelo usuário.

A chamada de procedimentos é trivial. A estrutura do interpretador contém uma estrutura de call frame tendo mais ou menos apenas um ponteiro para uma lista de variáveis ​​​​curtidas (que por sua vez são estruturas com dois campos: nome e valor). Quando um procedimento é chamado, um novo call frame é criado e colocado no topo do antigo. Quando o procedimento retorna, o quadro de chamada superior é destruído.

Dentro de cada grande programa há um pequeno programa tentando sair – Sir Tony Hoare.

Fonte: theverge

Mais recentes

PUBLICIDADE

WP Twitter Auto Publish Powered By : XYZScripts.com