College Online
0%

Tabela de Simbolos

Modulo 4 · Aula 2 ~22 min de leitura Nivel: Intermediario

Video da aula estara disponivel em breve

O que e uma Tabela de Simbolos

A tabela de simbolos e uma estrutura de dados que o compilador usa para armazenar informacoes sobre cada identificador no programa: seu nome, tipo, escopo, e localizacao. E construida durante a analise semantica e usada em todas as fases subsequentes.

Diagrama
Tabela de simbolos para:
  def calcular(taxa: float, bonus: float) -> float:
      resultado = taxa * 100 + bonus
      return resultado

Nome         | Tipo     | Escopo     | Categoria  | Linha
-------------|----------|------------|------------|------
calcular     | function | global     | funcao     | 1
taxa         | float    | calcular   | parametro  | 1
bonus        | float    | calcular   | parametro  | 1
resultado    | float    | calcular   | local      | 2

Escopos e Resolucao de Nomes

Linguagens com escopos aninhados (blocos, funcoes, classes) precisam de uma cadeia de escopos (scope chain). A resolucao de um nome busca do escopo mais interno para o mais externo:

Python
class SymbolTable:
    """Tabela de simbolos com escopos aninhados."""

    def __init__(self, parent=None, scope_name="global"):
        self.symbols = {}
        self.parent = parent
        self.scope_name = scope_name

    def define(self, name, info):
        """Define um simbolo no escopo atual."""
        if name in self.symbols:
            raise NameError(f"'{name}' ja definido em {self.scope_name}")
        self.symbols[name] = info

    def lookup(self, name):
        """Busca um simbolo: escopo atual, depois pai, depois avo..."""
        if name in self.symbols:
            return self.symbols[name]
        if self.parent:
            return self.parent.lookup(name)
        raise NameError(f"'{name}' nao definido")

    def enter_scope(self, name):
        """Cria um escopo filho."""
        return SymbolTable(parent=self, scope_name=name)

# Uso
global_scope = SymbolTable()
global_scope.define('PI', {'type': 'float', 'value': 3.14159})

func_scope = global_scope.enter_scope('calcular')
func_scope.define('taxa', {'type': 'float', 'category': 'param'})
func_scope.define('bonus', {'type': 'float', 'category': 'param'})

# Resolver 'PI' de dentro de func_scope:
print(func_scope.lookup('PI'))    # encontra no escopo pai
print(func_scope.lookup('taxa'))  # encontra no escopo atual
i
Lexical vs. Dynamic Scoping Na maioria das linguagens (Python, C, Java), o escopo e lexico (ou estatico): a resolucao de nomes depende de onde o codigo esta escrito, nao de onde e chamado. Em dynamic scoping (Bash, Emacs Lisp antigo), o escopo depende da cadeia de chamadas em runtime. Compiladores quase sempre lidam com scoping lexico.

No harness.os

O harness.os tem um sistema de resolucao de nomes analogo a uma tabela de simbolos. Project slugs, domain names, concern names, e tool names formam um namespace hierarquico:

Python
class HarnessSymbolTable:
    """Tabela de simbolos para o namespace do harness.os.

    Hierarquia de resolucao:
      project -> domain -> concern -> knowledge

    Exemplo de resolucao:
      "harness-os/build/governance/commit-hygiene"
       ^project   ^domain ^concern   ^knowledge
    """

    def __init__(self):
        self.projects = {}  # slug -> project info
        self.tools = {}     # tool_name -> tool info (MCP)

    def register_project(self, slug, info):
        self.projects[slug] = {
            'info': info,
            'domains': {},
        }

    def register_domain(self, project_slug, domain_name, info):
        proj = self.projects[project_slug]
        proj['domains'][domain_name] = {
            'info': info,
            'concerns': {},
        }

    def resolve(self, path):
        """Resolve um caminho como 'harness-os/build/governance'."""
        parts = path.split('/')
        current = self.projects.get(parts[0])
        if not current:
            raise NameError(f"Projeto '{parts[0]}' nao encontrado")
        if len(parts) > 1:
            current = current['domains'].get(parts[1])
            if not current:
                raise NameError(f"Domain '{parts[1]}' nao encontrado")
        if len(parts) > 2:
            current = current['concerns'].get(parts[2])
            if not current:
                raise NameError(f"Concern '{parts[2]}' nao encontrado")
        return current

    def register_tool(self, name, schema):
        """Registra uma tool MCP (analogo a declaracao de funcao)."""
        self.tools[name] = schema

    def resolve_tool(self, name):
        """Resolve uma tool MCP por nome."""
        if name not in self.tools:
            raise NameError(f"Tool '{name}' nao registrada")
        return self.tools[name]

Resumo

Exercicio

Projete uma tabela de simbolos para o harness.os que resolva: project slugs, domain names, concern names, knowledge chunk titles, e tool names (MCP). Implemente lookup com fallback hierarquico e teste com pelo menos 3 niveis de resolucao.

Verifique seu entendimento

Em lexical scoping, como o compilador resolve uma variavel que nao esta definida no escopo atual?

  • Busca na pilha de chamadas em runtime
  • Sobe a cadeia de escopos lexicos (escopo pai, avo, etc.) ate encontrar
  • Gera um erro imediatamente
  • Cria a variavel automaticamente no escopo global