prometeu-studio/docs/compiler/pbs/agendas/18.5. Ignored Call Results in Executable Lowering Agenda.md
2026-03-24 13:42:56 +00:00

4.4 KiB

Ignored Call Results in Executable Lowering Agenda

Status

Open

Domain Owner

docs/compiler/pbs

Este tema pertence ao domínio PBS do compiler porque afeta:

  • semântica prática de expression statement;
  • lowering executável para IRBackend/IRVM;
  • ergonomia de uso de SDKs e hosts que retornam status;
  • compatibilidade entre o que o código-fonte parece permitir e o que o pipeline realmente aceita.

Problema

Hoje uma chamada com retorno usada como statement isolado pode deixar valor sobrando na stack no lowering executável.

Exemplo real:

Gfx.set_sprite(...);

No estado atual, isso compila no frontend, mas pode falhar no pipeline backend com erro de validação de stack no RET da função, porque o resultado da call não foi consumido explicitamente.

Isso cria uma inconsistência operacional:

  1. o código parece válido para o autor;
  2. o frontend aceita a forma;
  3. o backend exige, na prática, um consumo manual do retorno, por exemplo:
let sprite_status = Gfx.set_sprite(...);

Contexto

O problema apareceu ao migrar o consumo de sprite em PBS para o contrato novo de Gfx.set_sprite, que retorna um status inteiro.

Os pontos observados no código atual são:

  • ExpressionStatement faz lowering apenas da expressão;
  • o lowering de CallExpr emite CALL_HOST, CALL_FUNC ou CALL_INTRINSIC com retSlots;
  • não há descarte automático do valor quando a expressão é usada apenas como statement;
  • o validador de IRVM exige que funções void retornem com stack height 0.

Na prática, isso transforma "ignorar retorno" em comportamento parcialmente suportado pela linguagem, mas não suportado pelo pipeline executável.

Opções

Opção A

Manter o comportamento atual e exigir consumo explícito de todo retorno em PBS.

Opção B

Permitir que expression statements descartem automaticamente o resultado quando a expressão produzir valor.

Opção C

Permitir descarte automático apenas para um subconjunto de calls, como hosts/SDKs anotados como status descartável.

Tradeoffs

Opção A

  • Prós:
    • regra simples no backend;
    • evita descarte implícito sem intenção.
  • Contras:
    • ergonomia ruim para APIs baseadas em status;
    • surpresa para autores, porque foo(); parece natural mas falha mais tarde;
    • expõe detalhe de stack do backend ao código-fonte.

Opção B

  • Prós:
    • comportamento esperado para statement de expressão;
    • reduz ruído em código de jogo e SDK;
    • alinha parsing, semântica prática e lowering executável.
  • Contras:
    • introduz descarte implícito;
    • exige regra clara para saber quando emitir POP.

Opção C

  • Prós:
    • mais controle semântico;
    • evita descarte implícito amplo.
  • Contras:
    • adiciona complexidade de contrato e metadata;
    • mistura política de produto/API dentro do lowering;
    • não resolve a expectativa geral sobre expression statement.

Recomendação

Seguir com a Opção B.

Direção recomendada:

  1. expression statement deve ser permitido mesmo quando a expressão produzir valor;
  2. o lowering executável deve emitir descarte explícito do resultado não usado;
  3. a regra deve ser geral para expressões com resultado materializado em stack, não especial para Gfx.set_sprite;
  4. testes de regressão devem cobrir host calls, callable calls e intrinsics com retorno ignorado.

Essa direção preserva a ergonomia esperada da linguagem e remove um vazamento indevido do modelo de stack do backend para o código PBS.

Perguntas em Aberto

  1. O descarte automático deve valer para qualquer expression statement com valor ou apenas para formas lowerables em v1?
  2. O frontend semântico deve emitir algum warning opcional para retorno ignorado, ou isso fica fora do escopo atual?
  3. O descarte deve acontecer somente no lowering executável ou também virar regra explícita de spec para statements?
  4. Existe algum caso em que o descarte automático possa mascarar bug real de usuário que hoje seria detectado mais cedo?

Próximo Passo Sugerido

Converter esta agenda em uma decision do domínio compiler/pbs fechando a política para expression statement com resultado ignorado.

Depois disso, abrir um pull-request/plan curto para:

  1. ajustar o lowering de ExpressionStatement;
  2. adicionar fixtures e testes de regressão no frontend/backend pipeline;
  3. propagar a regra para specs relevantes de statements e lowering.