
Imagine que temos um único arquivo, nomeado por hello.php.
<?php
$message = 'Hello World';
echo $message;Esse arquivo é basicamente texto contendo código-fonte PHP. Sozinho, ele não executa nada. Quem faz o trabalho é o runtime do PHP, e boa parte do núcleo de execução fica na Zend Engine.
arquivo .php
↓
Zend Engine
├─ lexer
├─ parser
├─ AST
├─ compilador → opcodes
└─ Zend VM → execução
Um dos primeiros passos do runtime, é ler o código-fonte caractere por caractere e agrupar esses caracteres em tokens com significado para a linguagem.
Considerando também os espaços e as quebras de linha do exemplo, a sequência fica assim:
"<?php\n" → T_OPEN_TAG
"\n" → T_WHITESPACE
$message → T_VARIABLE
" " → T_WHITESPACE
= → caractere "="
" " → T_WHITESPACE
'Hello World' → T_CONSTANT_ENCAPSED_STRING
; → caractere ";"
"\n\n" → T_WHITESPACE
echo → T_ECHO
" " → T_WHITESPACE
$message → T_VARIABLE
; → caractere ";"
O parser recebe os tokens do lexer, verifica se a sequência segue a gramática da linguagem e, se estiver válida, monta a AST que representa a estrutura do código.
hello.php
├── atribuição
│ ├── variável: $message
│ └── string: "Hello World"
│
└── echo
└── variável: $message
Depois que o parser gera a AST, o compilador da Zend Engine percorre essa árvore e a transforma em opcodes que pode virar algo próximo disso:
ASSIGN $message, "Hello World"
ECHO $message
RETURN 1
São essas instruções que a Zend VM executará para finalmente produzir nosso Hello World.
$ php hello.php
Hello World
PHP é interpretado ou compilado?
A resposta curta é: um pouco dos dois.
O código-fonte passa por uma etapa de compilação para opcodes e, depois, esses opcodes são executados pela Zend VM.
Então dizer que PHP é uma linguagem interpretada funciona como simplificação, mas agora sabemos que existe um processo de compilação acontecendo no meio do caminho.