prometeu-studio/docs/compiler/pbs/agendas/19.2. PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda.md

362 lines
13 KiB
Markdown

# PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda
## Status
Open
## Parent Agenda
This agenda derives from:
- `19. Globals, Synthetic Module Init, and FRAME_RET Agenda`
Expected fixed input from previous stage:
- `19.1. PBS Globals Surface, Identity, and Module Boundaries Agenda`
## Purpose
Define the observable lifecycle model of PBS once runtime globals exist.
This agenda must close:
- whether `[Init]` and `[Frame]` become official source markers;
- the relationship between module init and program init;
- boot one-shot behavior;
- failure policy;
- and the semantic role of the user's frame root.
## Domain Owner
`docs/compiler/pbs`
Este tema pertence ao domínio PBS porque define lifecycle observável da linguagem, não apenas mecanismo de backend.
## Context
Depois que `declare global` existir como storage runtime de módulo, o compiler precisará definir:
- quando os globals são materializados;
- em que ordem isso acontece;
- se existe um hook explícito de init de programa;
- se existe um init procedural por módulo separado do initializer declarativo de `global`;
- como a linguagem identifica o frame root do usuário;
- e o que acontece quando o boot falha.
Esta agenda ainda não decide a forma exata do wrapper published entrypoint nem o shape do IR. Ela define primeiro o comportamento observável que essas camadas posteriores terão de respeitar.
## Inputs Already Fixed Elsewhere
Os seguintes inputs devem ser tratados como fechados ou fortemente estáveis aqui:
- o modelo base de globals vindo de `19.1`;
- o initializer declarativo de `global` permanece restrito a primitivas, `new` e leitura de outras globals compatíveis com o dep graph;
- top-level `fn` não são permitidas em initializer de `global` em v1;
- `FRAME_SYNC` permanece como safepoint normativo;
- PBS v1 continua determinístico e single-threaded;
- esta fase continua evitando mudanças novas no runtime.
## Decisions To Produce
Esta agenda deve produzir direção suficiente para fechar:
1. se `[Init]` e `[Frame]` entram na surface oficial;
2. targets válidos, unicidade e assinaturas exigidas;
3. ordem entre module init, init de programa e frame;
4. política de boot one-shot;
5. política de falha;
6. papel semântico de `frame()` do usuário;
7. política de loops e host calls admissíveis durante init.
## Core Questions
1. PBS deve introduzir `[Init]` e `[Frame]` como atributos reservados?
2. `[Init]` deve ser permitido tanto por módulo quanto no init final de projeto?
3. `[Frame]` deve existir exatamente uma vez por programa?
4. `[Init]` deve existir no máximo uma vez por programa?
5. `[Init]` e `[Frame]` devem exigir assinatura fixa `fn ...() -> void`?
6. Todos os module inits devem rodar antes do `[Init]` do usuário?
7. A ausência de `[Init]` deve ser válida?
8. A ausência de `[Frame]` deve ser erro hard para programa executável?
9. Em caso de falha durante module init ou `[Init]`, o programa deve falhar definitivamente ou pode haver retry?
10. Qual é a definição semântica correta de `frame()` do usuário: root lógico do tick, callable publicado, ou apenas callable invocado por infraestrutura sintética futura?
11. Loops devem ser permitidos em init de módulo e init de projeto?
12. Host calls devem ser proibidas por padrão durante init?
13. Apenas host calls marcadas com `[InitAllowed]` devem ser admissíveis durante init?
14. Como a admissibilidade de `[InitAllowed]` é validada em compile time?
## Options
### Option A
Introduzir `[Init]` e `[Frame]` como markers reservados explícitos, com assinaturas fixas, `[Init]` opcional por módulo e por projeto, `[Frame]` obrigatório e único por projeto executável, permitindo init procedural por módulo e mantendo política restritiva de host interaction durante init.
### Option B
Introduzir apenas `[Frame]` e manter init inteiramente sintético, sem hook de programa do usuário nesta fase.
### Option C
Manter lifecycle implícito, sem markers source-level, e continuar derivando entrypoint/configuração fora da linguagem.
## Tradeoffs
### Option A
- Prós:
- deixa lifecycle explícito na linguagem;
- reduz dependência de configuração paralela;
- dá base clara para wrapper, manifest e lowering posteriores.
- Contras:
- amplia a surface de atributos reservados;
- exige validação de target, unicidade e assinatura.
### Option B
- Prós:
- escopo menor;
- adia parte da discussão de init.
- Contras:
- resolve só metade do lifecycle;
- pode forçar redesign quando o hook de init do usuário voltar.
### Option C
- Prós:
- menor custo imediato.
- Contras:
- mantém a autoridade do lifecycle fora da linguagem;
- enfraquece a coerência da série 19.
## Recommendation
Seguir com a **Option A**.
Direção recomendada:
1. `[Init]` e `[Frame]` devem ser markers reservados explícitos;
2. `declare global` sempre lowera para o init sintético do módulo owner;
3. `[Init]` de módulo deve ser opcional e executar depois de todos os `declare global` do módulo;
4. o init de projeto deve seguir o mesmo modelo, mas associado ao projeto que contém o `[Frame]`;
5. `[Init]` de projeto deve ser opcional;
6. `[Frame]` deve ser obrigatório para programa executável e único por projeto;
7. `[Init]` e `[Frame]` devem exigir assinatura fixa `fn name() -> void`;
8. boot deve ser one-shot;
9. falha de boot deve seguir direção fail-fast, salvo argumento forte em contrário;
10. loops devem ser permitidos em init de módulo e init de projeto;
11. host calls devem ser proibidas por padrão durante init;
12. apenas host calls com atributo reservado `[InitAllowed]` devem ser admissíveis durante init;
13. `[InitAllowed]` é atributo reservado de SDK, não userland.
## Additional Lifecycle Concerns
Esta agenda também precisa fechar a separação entre três camadas de bootstrap:
1. initializer declarativo de `global`;
2. init por módulo;
3. init de projeto.
Direção herdada da `19.1`:
- `global` materializa storage inicial;
- init de módulo executa lógica procedural de conveniência sobre globals do próprio módulo;
- init de projeto executa coordenação final do programa.
Com esse modelo:
- loops são legítimos em init de módulo e init de projeto, especialmente para carga e preparação de arrays e estruturas derivadas;
- a restrição normativa mais forte deve cair sobre host interaction;
- "bootstrap leve" continua sendo recomendação de design, não um limite impossível de verificar semanticamente.
## Current Direction
Os pontos abaixo já podem ser tratados como direção fechada desta agenda, salvo objeção nova forte:
1. `[Init]` e `[Frame]` entram como atributos reservados explícitos;
2. `declare global X: T = expr;` lowera sempre para o init sintético do módulo owner;
3. cada arquivo pode declarar opcionalmente um `[Init]` procedural próprio;
4. o `[Init]` de cada arquivo roda sempre depois das globals daquele arquivo e participa do init sintético do módulo;
5. existe também um init de projeto opcional, que é o `[Init]` associado ao projeto que contém o `[Frame]`;
6. `[Frame]` é obrigatório e único por projeto executável;
7. `[Init]` e `[Frame]` seguem a forma recomendada:
```pbs
[Init]
fn init() -> void { ... }
```
```pbs
[Frame]
fn frame() -> void { ... }
```
8. a assinatura exigida é sempre `fn name() -> void`;
9. loops são permitidos nos inits;
10. host calls são proibidas por padrão durante init;
11. apenas host calls com `[InitAllowed]` podem ser usadas durante init;
12. `[InitAllowed]` pertence às superfícies reservadas de SDK, não a userland;
13. falha de boot é fail-fast com mensagem coerente.
Também fica fechada a seguinte regra operacional:
14. o `[Init]` que estiver no mesmo arquivo que o `[Frame]` é o init de projeto;
15. `[Init]` em outros arquivos continuam sendo init de módulo;
16. `[Frame]` e o init de projeto devem ser co-localizados no mesmo arquivo por decisão deliberada de source organization.
17. cada arquivo pode declarar no máximo um `[Init]`;
18. cada módulo possui exatamente um init sintético de módulo, dentro do qual os inits por arquivo são ordenados e compostos;
19. a distinção entre init de módulo e init de projeto é apenas de ordenação e papel semântico, não de surface diferente;
20. como consequência, existe no máximo um `[Init]` de projeto por projeto executável.
21. arquivos sem globals podem declarar um `[Init]`, desde que continuem respeitando a regra de no máximo um `[Init]` por arquivo;
22. o `project init` segue exatamente a mesma assinatura `fn init() -> void`.
## Lifecycle Order Direction
Esta agenda também já aponta para a seguinte ordem lógica de bootstrap:
1. materialização das globals de cada arquivo do módulo conforme a ordem determinada pelo dependency graph;
2. execução do `[Init]` daquele arquivo, quando existir;
3. composição desses passos em um único init sintético do módulo;
4. depois do fechamento dos módulos necessários, execução do `[Init]` de projeto, quando existir;
5. entrada no primeiro `frame()`.
Lendo essa ordem de forma operacional:
1. cada arquivo inicializa suas próprias globals;
2. cada arquivo pode então executar seu `[Init]` opcional;
3. tudo isso se aninha dentro de um único init sintético por módulo;
4. o `[Init]` co-localizado com `[Frame]` é elevado a init de projeto por ordem e papel semântico.
Também fica fechada a seguinte direção adicional:
5. a ordem entre arquivos do mesmo módulo deve seguir a ordem derivada do `DependencyGraphAnaliser` das globals;
6. quando dois arquivos não tiverem dependência entre si, o compiler deve usar uma ordem determinística estável.
## Remaining Open Points
Com a direção já consolidada nesta agenda, não restam pontos substantivos em aberto dentro do boundary de `19.2`.
Os temas seguintes agora pertencem à `19.3`.
## InitAllowed Direction
Esta agenda fecha também o seguinte shape normativo inicial para `[InitAllowed]`:
1. `[InitAllowed]` é um atributo reservado sem argumentos em v1;
2. ele é válido apenas em host methods de SDK;
3. ele é inválido em userland;
4. ele é inválido em `fn`, `global`, `service` e demais superfícies que não sejam host methods de SDK;
5. seu papel é exclusivamente validar, em compile time, quais host calls podem aparecer durante init;
6. ele não faz distinção entre init de módulo e init de projeto;
7. a diferença entre esses inits é de ordenação e papel semântico, não de permissão separada de host call.
Exemplo recomendado:
```pbs
declare host Runtime {
[Host(module = "runtime", name = "random_u32", version = 1)]
[Capability(name = "runtime")]
[InitAllowed]
fn random_u32() -> int;
}
```
## Diagnostics Recommendation
Esta agenda fecha o seguinte catálogo mínimo de diagnósticos de lifecycle e bootstrap.
### 1. Project Init Must Be Colocated With Frame
Mensagem semântica recomendada:
- `project init must be colocated with frame`
### 2. Multiple Project Init Functions Detected
Mensagem semântica recomendada:
- `multiple project init functions detected`
### 3. Multiple Frame Functions Detected
Mensagem semântica recomendada:
- `multiple frame functions detected`
### 4. Missing Frame Function For Executable Project
Mensagem semântica recomendada:
- `missing frame function for executable project`
### 5. Invalid Init Signature
Mensagem semântica recomendada:
- `init function must have signature fn name() -> void`
### 6. Invalid Frame Signature
Mensagem semântica recomendada:
- `frame function must have signature fn name() -> void`
### 7. Host Call Not Allowed During Init
Mensagem semântica recomendada:
- `host call not allowed during init`
### 8. Invalid InitAllowed Target
Mensagem semântica recomendada:
- `InitAllowed is valid only on SDK host methods`
### 9. Boot Failed During Module Init
Mensagem semântica recomendada:
- `boot failed during module init`
### 10. Boot Failed During Project Init
Mensagem semântica recomendada:
- `boot failed during project init`
### 11. Multiple Module Init Functions Detected
Mensagem semântica recomendada:
- `multiple module init functions detected`
### 12. Init Attribute Target Invalid
Mensagem semântica recomendada:
- `Init attribute target invalid`
## Expected Spec Material
Se esta agenda fechar, a propagação esperada atinge pelo menos:
- `3. Core Syntax Specification.md`
- `4. Static Semantics Specification.md`
- `9. Dynamic Semantics Specification.md`
- `12. Diagnostics Specification.md`
## Non-Goals
Esta agenda não deve:
1. decidir o nome físico do wrapper published entrypoint;
2. decidir o nome físico do entrypoint no manifest;
3. definir shape de IR;
4. definir como `FRAME_RET` será reposicionado materialmente.
## Next Step
Depois de fechar esta agenda, abrir ou aprofundar:
- `19.3. Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda`