A cobertura de tradução é parcial. Consulte a fonte em inglês para a referência técnica completa. Ver versão em inglês →

Sistema de Módulos

Organize o seu código em módulos com importações explícitas e controlo de espaços de nomes.

Sistema de Módulos

O Sounio organiza o código estruturalmente através de módulos. Um ficheiro de código-fonte pode declarar-se como um módulo através de uma diretiva explícita module posicionada no início do documento, ou optar por permanecer num espaço de nomes partilhado (espaço de nomes plano ou flat namespace) caso essa declaração não seja efetuada.

Declaração de um Módulo

// Ficheiro: ir/profile.sio
module ir::profile

fn sprof_parse(data: &str) -> SprofProfile {
    // ...
}

fn sprof_lookup(profile: &SprofProfile, name: &str) -> i64 {
    // ...
}

A diretiva module ir::profile instrui o compilador a posicionar todas as definições presentes neste ficheiro sob o espaço de nomes qualificado ir::profile.

Importar Componentes

A diretiva use permite expor e trazer símbolos e caminhos qualificados para o escopo local de execução:

// Importação universal (Wildcard) — expõe todos os nomes públicos no escopo atual
use ir::profile::*

// As funções do módulo passam a estar acessíveis de forma direta
let profile = sprof_parse(data)
let count = sprof_lookup(profile, "main")

O Sounio também suporta a importação seletiva e restrita de símbolos específicos:

use ir::profile::{sprof_parse, sprof_lookup}

Nota de Fiabilidade: As importações universais (use modulo::*) revelam-se atualmente mais robustas do que as seleções explícitas de sub-símbolos. Para módulos que recorram a funções de apoio internas complexas, dê preferência ao uso de wildcards em caso de dúvida para evitar falhas de resolução do compilador.

Ficheiros em Espaço de Nomes Plano

Os ficheiros de código que omitam a declaração module partilham um espaço de nomes comum e plano (flat namespace). As suas definições internas ficam automaticamente expostas a qualquer outro ficheiro que partilhe este mesmo domínio, dispensando o recurso à diretiva use:

// Ficheiro: ir/normalize.sio
// (Nenhuma declaração de módulo presente)

fn normalize_instruction(instr: &!IrInstr) {
    // Disponível sem necessidade de importação nos restantes ficheiros planos
}

Esta abordagem é adotada de forma consistente por vários subsistemas do compilador self-hosted, incluindo normalize.sio, const_prop.sio, dce.sio e ssa.sio.

Regras de Resolução de Módulos

  1. Estrutura Declarada: Qualquer ficheiro demarcado com module X::Y tem de ser explicitamente importado através de use X::Y::* ou use X::Y::{nome}.
  2. Ambiente Plano: Ficheiros sem a diretiva de cabeçalho module integram o espaço de nomes plano, tornando as suas definições acessíveis globalmente sem importações.
  3. Ordem de Definição: Não são admitidas referências antecipadas (forward references). As funções de apoio (helpers) têm de preceder obrigatoriamente os seus respetivos chamadores no fluxo do ficheiro físico.
  4. Mapeamento de Caminhos: Os caminhos dos módulos refletem fielmente a estrutura física de ficheiros e pastas no sistema operativo: o módulo ir::profile corresponde ao ficheiro físico ir/profile.sio.

Coexistência de Padrões

O compilador self-hosted combina de forma coordenada ambos os estilos organizacionais:

// main.sio — Combina importações explícitas de módulos e resolução plana
use ir::ir::*           // Importação de módulo: IrFunction, IrModule, etc.
use ir::profile::*      // Importação de módulo: SprofProfile, sprof_parse, etc.
use ir::inline::*       // Importação de módulo: inl_run_pass, etc.

// Os ficheiros normalize.sio e const_prop.sio são planos e dispensam importações

Recomendações Práticas

  • Design de Componentes: Adote a cláusula module para bibliotecas públicas, interfaces expostas e componentes reutilizáveis que exijam uma demarcação de fronteiras clara.
  • Desenvolvimento Interno: Opte pelo espaço de nomes plano para acoplar de forma simples e direta ficheiros de implementação que partilhem múltiplos utilitários internos comuns.
  • Tipagem da AST: Utilize sempre importações universais (use parser::ast::*) ao interagir com definições de Árvores de Sintaxe Abstrata (AST) para assegurar o correto funcionamento da resolução de operadores sobre variantes de enumerações.