prometeu-studio/docs/compiler/pbs/agendas/19. Globals, Synthetic Module Init, and FRAME_RET Agenda.md

31 KiB

Globals, Synthetic Module Init, and FRAME_RET Agenda

Status

Open

Purpose

Define how PBS should introduce runtime globals and lifecycle-driven executable bootstrap without changing the runtime contract in this phase.

This document is the umbrella agenda for topic 19.

It exists to:

  • keep the full problem framed in one place;
  • define the dependency order between discussions;
  • prevent later discussions from re-opening earlier boundaries casually;
  • and provide the parent reference for any follow-up agendas created under this topic.

This agenda must converge on:

  • the source-level model for mutable module storage;
  • the lifecycle model for module init, optional program init, and frame execution;
  • the ownership of FRAME_RET once the published entrypoint stops being the user's frame() directly;
  • the migration path from explicit FrontendSpec entrypoint configuration to source-derived PBS entrypoint discovery.

Domain Owner

docs/compiler/pbs

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

  • a surface language de declarações top-level;
  • a detecção de entrypoints pelo frontend PBS;
  • o modelo de inicialização de módulo e programa;
  • o lowering de entrypoint de frame;
  • a relação entre entrypoint lógico do usuário e entrypoint publicado no artefato;
  • o contrato interno entre frontend, IRBackend, IRVM lowering e bytecode final.

Nesta fase, o owner continua sendo compiler/pbs mesmo quando o resultado reutilizar capacidades já existentes da VM, porque a discussão é sobre como o compiler vai expor e orquestrar essas capacidades.

Problema

Hoje o PBS não expõe variáveis globais mutáveis de módulo.

O topo do arquivo aceita declare const, mas declare const é compile-time e não storage runtime. Isso impede formas como:

declare struct Vec2(x: int, y: int);

declare global origin: Vec2 = new Vec2(0, 0);

Ao mesmo tempo:

  1. a VM já tem suporte operacional para globals por slot;
  2. o compiler não modela globals no IR executável atual;
  3. o entrypoint de frame do usuário hoje coincide, na prática, com a função que delimita o frame lógico;
  4. o pipeline atual usa FRAME_RET no final desse fluxo de frame lógico.
  5. a seleção do entrypoint ainda depende de configuração explícita em FrontendSpec, em vez de ser derivada da própria source language do PBS.

Se introduzirmos declare global, o compiler precisará definir:

  1. como globals são inicializados;
  2. quando essa inicialização roda;
  3. como garantir execução uma única vez;
  4. como conviver com um init() custom do usuário;
  5. como detectar de forma canônica quais funções do usuário exercem os papéis de init e frame;
  6. como preservar o contrato de frame lógico quando a função publicada deixar de ser a função frame() original do usuário.

Contexto

O estado atual do sistema é:

  • PBS proíbe let top-level e não expõe storage mutável de módulo;
  • declare const é avaliado em compile time e pode ser inlinado/foldado;
  • inicializadores não constantes como new, call sugar, some, none, if, switch e outras formas executáveis não pertencem ao modelo de declare const;
  • a VM do runtime já possui GetGlobal e SetGlobal;
  • o IRBackend executável atual modela locals, calls, jumps e literais, mas não modela globals;
  • o entrypoint de frame hoje é tratado como raiz do frame lógico, inclusive para o ponto final onde FRAME_RET é emitido;
  • o frontend PBS ainda depende de configuração explícita em FrontendSpec para saber qual callable é o entrypoint publicado;
  • hoje isso aparece como acoplamento a nomes/configuração que deveriam ser deduzidos pela própria linguagem.

O cenário motivador é permitir globals de módulo no PBS sem exigir, nesta fase, mudança de runtime.

Também queremos aproveitar essa discussão para mover a detecção de entrypoint para a source language do PBS, usando atributos explícitos:

[Init]
fn init() -> void {}

[Frame]
fn frame() -> void {}

Essa direção permitiria ao frontend PBS:

  1. localizar explicitamente o init do usuário;
  2. localizar explicitamente o frame root do usuário;
  3. montar o wrapper sintético final sem depender de configuração paralela em FrontendSpec;
  4. eliminar, nesta linha de evolução, a configuração explícita atual de entrypoint no registry/spec do frontend.

Esta agenda também cobre a extensão desse modelo para discutir:

  1. se [Init] deve existir apenas como hook final de programa ou também como surface por módulo;
  2. qual é exatamente o comportamento operacional de [Frame] como root lógico de frame do usuário;
  3. como [Init] por módulo, [Init] final de programa, wrapper sintético e FRAME_RET se compõem sem ambiguidade.

Isso empurra a solução para o compiler:

  1. synth de init por módulo;
  2. synth de wrapper do frame published entrypoint;
  3. eventual símbolo privado boot_done;
  4. redefinição do ponto onde o frame lógico realmente termina;
  5. detecção de init/frame a partir de atributos de source;
  6. remoção progressiva das configs explícitas atuais em FrontendSpec.

Inputs

Relevant inputs already present in the repository:

  • docs/vm-arch/ISA_CORE.md already exposes GET_GLOBAL and SET_GLOBAL;
  • docs/compiler/pbs/specs/13. Lowering IRBackend Specification.md currently requires a canonical executable entrypoint to be declared through FrontendSpec;
  • docs/compiler/pbs/specs/7. Cartridge Manifest and Runtime Capabilities Specification.md currently expects PBS v1 manifest entrypoint to align with frontend-declared frame.

The discussion here must preserve compatibility with those contracts unless it explicitly proposes the propagation work needed to evolve them.

Core Questions

  1. PBS deve introduzir declare global como declaração top-level distinta de declare const?
  2. declare global deve aceitar inicializadores executáveis como new Vec2(...), calls e outras expressões lowerables?
  3. O compiler deve sintetizar um module init por módulo que contenha declare global?
  4. A inicialização deve rodar eager no boot lógico do programa ou lazy no primeiro frame?
  5. Deve existir um init() custom do usuário que roda depois de todos os module inits e antes do primeiro frame()?
  6. O PBS deve introduzir atributos explícitos [Init] e [Frame] para identificar as funções corretas do usuário?
  7. A descoberta de entrypoint no frontend PBS deve deixar de depender de configuração explícita em FrontendSpec?
  8. [Init] deve poder existir também em escopo/módulo de forma declarativa para orientar module init explícito, ou o compiler deve manter module init sempre totalmente sintético?
  9. Qual é o contrato preciso de comportamento de [Frame] no PBS: callable obrigatório, assinatura fixa, frequência esperada e relação com o frame lógico publicado?
  10. O published frame entrypoint deve passar a ser um wrapper sintético, por exemplo __pbs_frame(), em vez do frame() do usuário?
  11. FRAME_RET deve continuar significando "fim do frame lógico" e apenas mudar de owner, saindo da função do usuário para o wrapper sintético?
  12. Como o compiler deve tratar ordem topológica, dependências e ciclos entre globals de módulos distintos?
  13. Qual política vale quando algum module init ou init() do usuário falha: retry no próximo frame, fail-fast, ou outra forma?
  14. Globals exportados por mod.barrel devem se comportar como storage compartilhado de módulo ou como snapshot/importação por valor?

Inputs Already Fixed Elsewhere

Os seguintes pontos já parecem fixos ou fortemente estabelecidos e não devem ser contraditos nesta agenda:

  • a VM já suporta globals em nível de bytecode/execução;
  • declare const não é storage mutável/runtime-initialized;
  • o runtime já sabe executar um entrypoint published por frame;
  • FRAME_RET já é usado como marcador do fim de um frame lógico;
  • o frontend PBS hoje ainda carrega configuração explícita de entrypoint fora da source language;
  • nesta fase queremos evitar mudanças novas no runtime e concentrar a evolução no compiler.

Decisions To Produce

Como umbrella agenda, esta agenda não deve tentar fechar toda a solução normativa de uma vez.

Ela deve sair com:

  1. a decomposição oficial do tema em discussões derivadas;
  2. a ordem canônica dessas discussões;
  3. os inputs e outputs esperados de cada boundary;
  4. a lista de artefatos que não podem ser editados antes do boundary anterior fechar.

Depois que as discussões derivadas fecharem, o conjunto deve produzir direção suficiente para virar uma decision cobrindo pelo menos:

  1. a surface syntax e o modelo semântico de declare global;
  2. o modelo de bootstrap entre module init sintético, [Init] de programa e [Frame];
  3. o owner real do frame lógico publicado e o ponto correto de emissão de FRAME_RET;
  4. a política de descoberta de entrypoint a partir da source language do PBS;
  5. a política de ordenação, ciclos e falhas para globals e module init;
  6. a política de imports/exports para globals entre módulos.

Options

Option A

Adicionar declare global, introduzir [Init] e [Frame] como superfícies explícitas para lifecycle/entrypoint, discutir [Init] final vs [Init] por módulo, gerar module init sintético por módulo, gerar wrapper sintético de frame published entrypoint e mover o FRAME_RET para esse wrapper.

Option B

Adicionar declare global, mas exigir init totalmente estático ou restrito, sem init() custom do usuário e sem wrapper published separado do frame() atual.

Option C

Não adicionar declare global agora; manter apenas declare const e postergar a discussão até existir um modelo maior de bootstrap/program lifecycle.

Option D

Adicionar declare global, mas exigir lazy materialization no primeiro acesso em vez de module init explícito por ordem topológica.

Tradeoffs

Option A

  • Prós:
    • modelo explícito e fácil de explicar;
    • acomoda declare global com inicializadores realmente executáveis;
    • faz o PBS declarar na própria linguagem quais são os callables de init e frame;
    • abre espaço para discutir de forma unificada init por módulo, init final e root de frame;
    • permite init() custom do usuário sem mudar o runtime;
    • preserva o significado de FRAME_RET como fim do frame lógico;
    • remove um acoplamento indesejado entre frontend PBS e configuração manual de entrypoint em FrontendSpec.
  • Contras:
    • exige nova modelagem no compiler para globals, init synthesis e published frame wrapper;
    • exige regras novas de atributo e validação de unicidade para [Init] e [Frame];
    • obriga decisão clara sobre ordem, ciclos e falhas;
    • muda a relação atual entre frame() do usuário e entrypoint publicado.

Option B

  • Prós:
    • escopo menor;
    • reduz a superfície de lifecycle;
    • pode evitar parte da complexidade de wrapper e boot state.
  • Contras:
    • resolve mal o caso motivador com new Vec2(...);
    • produz uma feature de globais com restrição semântica forte demais;
    • deixa o init() do usuário para outra rodada e pode forçar redesign posterior.

Option C

  • Prós:
    • nenhum risco imediato em pipeline/backend;
    • preserva o estado atual do compiler.
  • Contras:
    • não resolve o caso desejado;
    • mantém uma lacuna entre capacidade da VM e surface language do PBS;
    • posterga um problema arquitetural que já apareceu de forma concreta.

Option D

  • Prós:
    • evita bootstrap eager explícito;
    • pode reduzir custo de init em módulos não usados.
  • Contras:
    • complica determinismo e observabilidade;
    • torna mais difícil explicar dependências entre módulos;
    • aumenta risco semântico para reentrância, ciclos e ordem de efeitos;
    • parece desnecessariamente sofisticado para v1.

Recommendation

Seguir com a Option A.

Direção recomendada para discussão:

  1. introduzir declare global como nova declaração top-level distinta de declare const;
  2. permitir inicializadores executáveis lowerables, incluindo new e calls compatíveis com o modelo de lowering executável;
  3. sintetizar um module init por módulo owner de globals;
  4. ordenar os module inits de forma determinística e topológica;
  5. introduzir [Init] e [Frame] como superfícies explícitas de detecção do init/frame do usuário;
  6. remover da evolução do PBS a dependência de configuração explícita de entrypoint em FrontendSpec, migrando a seleção para a análise da source language;
  7. discutir explicitamente se [Init] por módulo será uma surface do usuário ou se módulo continuará com init apenas sintético;
  8. permitir um init() custom opcional do usuário, executado depois de todos os module inits;
  9. publicar um wrapper sintético de frame, por exemplo __pbs_frame(), como verdadeiro frame root;
  10. tratar frame() do usuário como callable normal invocado por esse wrapper;
  11. manter FRAME_RET como marcador do fim do frame lógico, mas emitido no wrapper sintético publicado em vez de no frame() do usuário;
  12. manter toda a primeira fase restrita ao compiler e ao backend pipeline, sem novos requisitos para o runtime além dos contratos já existentes.

Essa recomendação ainda deixa alguns pontos para fechamento na decision, mas já estabelece um shape arquitetural coerente:

  • storage global pertence ao módulo owner;
  • bootstrap observável pertence ao compiler, não ao runtime;
  • frame() do usuário deixa de ser o entrypoint publicado e passa a ser o root lógico invocado pelo wrapper;
  • FRAME_RET continua significando fim do frame lógico, apenas com novo owner sintético;
  • a seleção de entrypoint deixa de ser configuração paralela e vira semântica explícita da linguagem.

Open Questions

  1. O nome surface deve ser exatamente declare global, ou outra forma top-level?
  2. Globals devem exigir initializer obrigatório em v1, ou existirão shells reservados parecidos com builtin const?
  3. [Init] e [Frame] devem ser atributos reservados do PBS ou outra forma de marker surface?
  4. [Init] deve exigir assinatura fixa fn init() -> void?
  5. [Frame] deve exigir assinatura fixa fn frame() -> void?
  6. Deve existir no máximo um [Init] e um [Frame] por programa, por módulo owner, ou por outro escopo?
  7. Module init deve permanecer sempre sintético em v1, ou o usuário pode anotar hooks por módulo em alguma forma futura?
  8. A política de falha de init deve ser fail-fast definitivo no boot, ou existe algum caso legítimo para retry controlado?
  9. Reexport de globals entre módulos deve preservar identidade de storage do owner original ou materializar aliases/import bindings sem storage próprio?
  10. O manifest entrypoint deve continuar expondo frame por compatibilidade nominal ou passar a refletir o símbolo sintético publicado?

Main Difficulties

Os principais pontos de dificuldade desta agenda não são sintáticos; eles estão na composição entre contratos já existentes.

1. declare global colide com o recorte atual de declare const

Hoje a semântica estática do PBS fixa que:

  • declare const entra no value namespace;
  • declare const não materializa storage mutável runtime;
  • inicializadores de declare const pertencem a um subset estritamente compile-time;
  • dependências entre declare const são acíclicas e resolvidas por análise de dependência, não por ordem textual.

Introduzir declare global exige decidir o que é reaproveitado desse modelo e o que deixa de valer:

  • namespace e visibilidade podem reaproveitar parte do modelo atual;
  • constant evaluation não pode ser reutilizada como está;
  • o modelo de dependência deixa de ser apenas compile-time e passa a produzir efeitos runtime.

2. A surface de atributos hoje tem um conjunto reservado fechado

O PBS já trata atributos como metadata compile-time com lowering explícito apenas quando outra spec define esse efeito.

Isso é favorável para [Init] e [Frame], mas cria trabalho em três frentes:

  • reservar novos atributos no conjunto normativo;
  • definir targets válidos, unicidade e diagnóstico;
  • definir o lowering sem deixar atributos "soltos" como metadata sem efeito operacional claro.

3. O entrypoint publicado hoje ainda está acoplado ao FrontendSpec

Existe uma obrigação atual em 13. Lowering IRBackend Specification.md para o frontend declarar um EntrypointRef canônico.

A agenda 19 quer mover a descoberta para a source language, mas isso abre uma transição delicada:

  • PBS precisa derivar esse EntrypointRef da source language;
  • o contrato de IRBackend não deve perder determinismo;
  • a migração não pode deixar coexistirem por muito tempo duas autoridades independentes para entrypoint.

4. O manifest ainda assume frame como callable publicado

7. Cartridge Manifest and Runtime Capabilities Specification.md hoje sugere alinhamento nominal entre manifest entrypoint e callable frame.

Se o compiler publicar __pbs_frame():

  • ou o manifest passa a refletir o símbolo sintético real;
  • ou o manifest preserva um nome lógico enquanto o símbolo real do artefato muda;
  • ou a pipeline passa a distinguir entrypoint lógico e entrypoint físico.

Sem fechar isso, a solução de wrapper fica tecnicamente incompleta.

5. FRAME_RET hoje coincide com o fim do callable do usuário

O ponto difícil não é só "mover um opcode". É redefinir qual callable delimita semanticamente o frame lógico:

  • frame() do usuário continua sendo apenas código de frame;
  • o wrapper sintético vira o owner do frame published entrypoint;
  • FRAME_RET continua com o mesmo significado semântico, mas sua posição material muda.

Isso afeta lowering, testes de conformance e a forma de explicar o modelo da linguagem.

6. Globals intermodulares introduzem um problema novo de identidade e ordem

Hoje declare const exportado via mod.barrel é simples porque não há storage mutável compartilhado.

Com declare global, a agenda precisa fechar:

  • quem é o owner real do storage;
  • o que um import recebe: binding para o owner ou cópia/snapshot;
  • como ciclos entre módulos são detectados;
  • se init pode ler globals de módulos predecessores;
  • qual é a ordem determinística entre módulos quando há efeitos de inicialização.

7. A política de falha deixa de ser apenas rejeição de build

Hoje boa parte do pipeline falha antes da emissão.

Com module init e init() do usuário, surge um problema runtime-observable:

  • o que acontece quando o boot parcial falha;
  • se o programa entra em estado terminal;
  • se existe retry;
  • como isso se relaciona com o fato de FRAME_SYNC permanecer o safepoint normativo.

Work Boundaries

Para manter a agenda executável e evitar mistura de artefatos, o trabalho pode ser separado nos seguintes boundaries.

Boundary A. Surface Language and AST

Owner principal: syntax + AST.

Inclui:

  • gramática de declare global;
  • superfície de atributos [Init] e [Frame];
  • targets permitidos desses atributos;
  • novos nós ou flags obrigatórios no AST para globals e lifecycle markers.

Pergunta de fechamento:

  • o parser apenas aceita as superfícies ou já impõe parte das restrições estruturais de target/shape?

Boundary B. Static Semantics and Linking

Owner principal: static semantics + linking.

Inclui:

  • namespace e visibilidade de declare global;
  • regras de initializer obrigatório ou opcional;
  • compatibilidade de tipo do initializer;
  • unicidade e assinatura válida para [Init] e [Frame];
  • regras de import/export/barrel para globals;
  • detecção de ciclos de dependência entre globals;
  • política de identidade do storage através de imports e reexports.

Pergunta de fechamento:

  • globals entram no mesmo value namespace de let/declare const ou exigem distinção semântica adicional apesar do namespace compartilhado?

Boundary C. Dynamic Semantics and Lifecycle Model

Owner principal: dynamic semantics.

Inclui:

  • ordem observável entre module init, [Init] de programa e [Frame];
  • definição de boot one-shot;
  • política de falha de init;
  • contrato semântico de [Frame] como raiz lógica do tick/frame do usuário;
  • relação entre frame lógico do usuário e entrypoint efetivamente publicado.

Pergunta de fechamento:

  • o programa tem dois conceitos distintos, logical frame root e published runtime entrypoint, ou a spec tenta esconder essa distinção do usuário?

Boundary D. IR and Backend Lowering

Owner principal: lowering executável.

Inclui:

  • representação de globals no IRBackend ou boundary imediatamente anterior;
  • synthesis de module init;
  • synthesis de wrapper published entrypoint;
  • materialização do guard one-shot de boot;
  • reposicionamento do FRAME_RET;
  • preservação do EntrypointRef canônico para o restante do backend.

Pergunta de fechamento:

  • globals entram como primitivo explícito no IR ou aparecem apenas em lowering posterior antes de IRVM/bytecode?

Boundary E. Artifact and Manifest Publication

Owner principal: artifact contracts.

Inclui:

  • nome do entrypoint exposto no manifest;
  • relação entre callable do usuário, símbolo sintético e entrypoint published;
  • compatibilidade com o contrato atual do cartridge manifest;
  • possíveis ajustes na leitura de tooling sobre qual callable é o entrypoint "real".

Pergunta de fechamento:

  • o manifest publica identidade lógica da linguagem ou identidade física do artefato executável?

Boundary F. Diagnostics and Conformance

Owner principal: diagnostics + fixture model.

Inclui:

  • diagnósticos para target inválido de [Init] e [Frame];
  • duplicidade ou ausência de markers obrigatórios;
  • initializer inválido de declare global;
  • ciclos intra/inter-módulo;
  • imports/reexports ilegais de globals;
  • fixture coverage para init ordering, wrapper published entrypoint e FRAME_RET.

Pergunta de fechamento:

  • quais erros pertencem ao frontend/linking e quais só podem ser cobertos por fixtures de toolchain completo?

Discussion Order

As discussões derivadas desta umbrella agenda devem seguir a ordem abaixo.

O objetivo da ordem é simples:

  • fechar primeiro autoridade semântica e surface;
  • depois fechar comportamento observável;
  • só então descer para lowering, artefato publicado e conformance.

Stage 1. Globals Surface and Static Identity

Boundary owner:

  • Boundary A. Surface Language and AST
  • Boundary B. Static Semantics and Linking

Esta discussão deve fechar primeiro porque todas as outras dependem da definição do que é um global no PBS.

Ela precisa decidir:

  • a forma exata de declare global;
  • initializer obrigatório ou opcional;
  • namespace, visibilidade e barrel/export/import;
  • identidade do storage owner;
  • política de reexport;
  • ciclos e dependências entre globals em nível de linking/static semantics.

Sem esse fechamento:

  • lifecycle ainda não sabe o que precisa inicializar;
  • lowering ainda não sabe que entidade precisa materializar;
  • manifest ainda não sabe se está publicando símbolos que dependem de storage global importado.

Stage 2. Lifecycle Markers and Program Bootstrap Semantics

Boundary owner:

  • Boundary C. Dynamic Semantics and Lifecycle Model

Esta discussão vem depois de Stage 1 porque init e frame só fazem sentido quando o modelo de globals já estiver fixado.

Ela precisa decidir:

  • se [Init] e [Frame] entram como superfícies oficiais;
  • unicidade e assinatura desses markers;
  • ordem entre module init, [Init] de programa e [Frame];
  • política de boot one-shot;
  • política de falha;
  • papel semântico exato de frame() do usuário.

Sem esse fechamento:

  • o wrapper sintético não tem contrato observável estável;
  • FRAME_RET não tem owner definido;
  • qualquer modelagem de IR corre risco de materializar o comportamento errado.

Stage 3. Published Entrypoint, Wrapper Ownership, and FRAME_RET

Boundary owner:

  • Boundary C. Dynamic Semantics and Lifecycle Model
  • Boundary D. IR and Backend Lowering
  • Boundary E. Artifact and Manifest Publication

Esta discussão depende de Stage 2 porque ela não decide mais "o que é lifecycle"; ela decide como lifecycle é publicado.

Ela precisa decidir:

  • se o published entrypoint é um wrapper sintético;
  • qual é a relação entre frame() do usuário e esse wrapper;
  • onde FRAME_RET passa a ser emitido;
  • se o manifest expõe entrypoint lógico, entrypoint físico ou ambos;
  • como o EntrypointRef do frontend continua determinístico durante a transição.

Sem esse fechamento:

  • não existe contrato estável para lowering final;
  • specs de manifest e IRBackend ficam em tensão;
  • o tooling pode continuar com duas autoridades concorrentes para entrypoint.

Stage 4. IR Representation and Lowering Mechanics

Boundary owner:

  • Boundary D. IR and Backend Lowering

Esta discussão vem depois de Stage 3 porque a forma do IR depende do que exatamente precisa ser publicado e executado.

Ela precisa decidir:

  • se globals entram como primitivo explícito do IR ou apenas em lowering posterior;
  • como module init é representado;
  • como o guard de boot é materializado;
  • como o wrapper published entrypoint é emitido;
  • como FRAME_RET é reposicionado mantendo o mesmo significado.

Sem esse fechamento:

  • código pode ser implementado cedo demais sobre contratos ainda móveis;
  • a propagação para specs gerais de lowering fica prematura;
  • testes de backend podem congelar um shape errado.

Stage 5. Diagnostics, Gates, and Conformance Coverage

Boundary owner:

  • Boundary F. Diagnostics and Conformance

Esta discussão deve vir por último porque ela consolida o que as anteriores já fixaram.

Ela precisa decidir:

  • catálogo mínimo de diagnósticos novos;
  • divisão entre erro de syntax/AST, linking/static semantics, lowering e toolchain;
  • fixtures obrigatórios para globals, lifecycle, wrapper e entrypoint publication;
  • critérios de aceite para a migração de FrontendSpec entrypoint config para source-derived entrypoint discovery.

Fazer isso antes cria dois riscos:

  • congelar diagnósticos para regras ainda instáveis;
  • ou escrever fixtures de conformance que depois precisam ser reabertas por mudança arquitetural.

Derived Agenda Outline

Se quisermos quebrar a umbrella agenda em agendas filhas, a ordem recomendada é:

  1. 19.1. PBS Globals Surface, Identity, and Module Boundaries Agenda
  2. 19.2. PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda
  3. 19.3. Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda
  4. 19.4. Globals and Lifecycle Lowering to IRBackend/IRVM Agenda
  5. 19.5. Diagnostics, Manifest Propagation, and Conformance Coverage Agenda

Cada agenda filha deve declarar explicitamente:

  • que deriva da umbrella agenda 19;
  • quais stages anteriores já são input fixo;
  • e quais outputs ela precisa entregar para a agenda seguinte.

Boundary Locking Rules

Para evitar que discussões posteriores prejudiquem as anteriores, esta umbrella agenda fixa as seguintes regras de sequenciamento:

  1. 19.2 não redefine surface syntax ou identidade de globals já fechadas em 19.1.
  2. 19.3 não redefine o significado semântico de [Init], [Frame] ou boot ordering já fechados em 19.2.
  3. 19.4 não reabre decisões de linguagem ou de lifecycle; ela apenas escolhe a representação e o mecanismo de lowering compatíveis com elas.
  4. 19.5 não reabre arquitetura; ela consolida diagnostics, manifest propagation e coverage.
  5. Qualquer ponto que force reabertura de stage anterior deve voltar explicitamente para a agenda filha owner correta, em vez de ser resolvido informalmente na etapa posterior.

Likely Propagation Targets

Mesmo sem virar decision ainda, esta agenda já mostra impacto provável nos seguintes artefatos.

PBS Specs

  • 3. Core Syntax Specification.md
  • 4. Static Semantics Specification.md
  • 9. Dynamic Semantics Specification.md
  • 11. AST Specification.md
  • 12. Diagnostics Specification.md
  • 13. Lowering IRBackend Specification.md
  • 7. Cartridge Manifest and Runtime Capabilities Specification.md

Cross-Domain / VM Architecture

  • docs/vm-arch/ISA_CORE.md provavelmente não precisa mudar em capability, mas precisa ser referenciado explicitamente como base de GET_GLOBAL/SET_GLOBAL;
  • specs gerais de lowering fora de docs/compiler/pbs podem precisar propagação posterior se IRBackend ganhar representação explícita de globals ou novo contrato para entrypoint published.

Compiler / Implementation Areas

  • parser e AST model;
  • linking/resolution;
  • static semantics;
  • IR model do frontend PBS;
  • executable lowering para IRBackend e IRVM;
  • montagem do manifest/cartridge metadata;
  • suites de fixture de frontend, lowering e toolchain.

Boundary Risks

Se os boundaries acima não forem respeitados, os riscos mais prováveis são:

  1. criar declare global como açúcar superficial sem lifecycle coerente;
  2. introduzir [Init] e [Frame] sem autoridade clara sobre FrontendSpec;
  3. mover FRAME_RET sem redefinir com precisão o owner do frame lógico;
  4. resolver globals intra-módulo mas deixar imports/reexports semanticamente ambíguos;
  5. fechar a solução do compiler sem fechar o contrato do manifest;
  6. misturar nesta agenda decisões de produto/runtime que deveriam continuar fora de escopo.

Expected Spec Material

Se esta agenda virar decision, a propagação esperada deve atingir pelo menos:

  • spec de declarações top-level do PBS para introduzir declare global;
  • spec de lifecycle/entrypoint attributes para [Init] e [Frame];
  • spec de lowering executável/IRBackend para module init synthesis, wrapper published entrypoint e ownership de FRAME_RET;
  • spec de cartridge manifest para esclarecer a relação entre entrypoint lógico do usuário e entrypoint publicado no artefato;
  • diagnósticos de validação para unicidade, assinatura inválida, ciclos de init e uso incorreto de globals.

Non-Goals

Esta agenda não deve:

  1. redesenhar o runtime ou introduzir novas instruções de VM;
  2. escrever a spec normativa final de globals e lifecycle;
  3. redefinir o modelo geral de módulos do compiler fora do necessário para globals/init;
  4. resolver todos os possíveis hooks futuros de programa além de [Init] e [Frame];
  5. discutir otimizações de performance de init além do necessário para garantir semântica determinística.

Next Step

Usar esta agenda como parent reference e abrir as agendas filhas na ordem abaixo:

  1. 19.1. PBS Globals Surface, Identity, and Module Boundaries Agenda
  2. 19.2. PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda
  3. 19.3. Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda
  4. 19.4. Globals and Lifecycle Lowering to IRBackend/IRVM Agenda
  5. 19.5. Diagnostics, Manifest Propagation, and Conformance Coverage Agenda

Somente depois do fechamento dessas agendas derivadas esta linha deve virar uma decision consolidada em docs/compiler/pbs/decisions.