690 lines
31 KiB
Markdown
690 lines
31 KiB
Markdown
# 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:
|
|
|
|
```pbs
|
|
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:
|
|
|
|
```pbs
|
|
[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`.
|