# **SPEC_VM.md — Holodeck VM v0.1**

*Máquina Virtual stack-based minimalista para a linguagem Neuro (NL v0.1)*

---

# 📘 **1. Objetivo**

A Holodeck VM v0.1 é:

* extremamente simples,
* 100% determinística,
* baseada em **stack**,
* orientada a **funções puras**,
* suficiente para executar programas definidos no SPEC_SYNTAX.md,
* mapeando diretamente o SPEC_IR.md.

Ela será escrita inicialmente em Python (ou C), mas o presente documento é **agnóstico de implementação**: descreve apenas as regras formais.

---

# 📗 **2. Arquitetura Geral**

A VM possui:

1. **Operand Stack**
   Usada para avaliar expressões e passar valores entre instruções.

2. **Call Stack**
   Contém **frames de função**, incluindo:

   * variáveis locais (arguments-only na v0.1),
   * instruções da função,
   * Instruction Pointer (IP),
   * referência ao frame anterior.

3. **Function Table**
   Um dicionário:

   ```
   nome → { arity, instrucoes }
   ```

4. **Estado Global**
   Apenas:

   * tabela de funcoes,
   * stack,
   * call stack.

Não existe heap nem GC na v0.1.

---

# 📙 **3. Representação de uma Função**

Uma função é descrita como:

```
{
  "name": "fib",
  "arity": 1,
  "instructions": [
      ... lista de instruções IR ...
  ]
}
```

Chamadas são feitas por nome + número de argumentos.

Não existe escopo lexical ainda.

---

# 📕 **4. Representação de um Frame**

Cada frame da call stack contém:

```
Frame:
  locals: map { nome → valor }     # Apenas argumentos na v0.1
  instrs: lista de instruções
  ip: índice da próxima instrução  # Começa em 0
  return_to: referência ao frame anterior
```

Valor de retorno:

* Após `RET`, o topo da stack contém o valor produzido pela função.
* O frame é descartado.
* A execução retorna ao frame anterior.

---

# 📘 **5. Ciclo de Execução (Run Loop)**

A VM repete:

```
1. ler instrucao atual do frame corrente (instr = instrs[ip])
2. ip = ip + 1
3. executar instrucao
4. possivel alterar ip (saltos)
5. possivel trocar de frame (CALL/RET)
```

A execução termina quando:

* o frame atual é `__main__/0`,
* e um `RET` é executado.

O valor restante no topo da stack é o valor final do programa.

---

# 📗 **6. Modelo de Dados**

A v0.1 suporta apenas:

* inteiros (não negativos),
* booleanos representados como inteiros (`0` e `1`).

Não existem strings, floats, arrays, objetos, closures.

---

# 📙 **7. Instruções da VM (v0.1)**

Cada instrução é executada sobre a operand stack.

Aqui estão descritas formalmente:

---

## **7.1. `PUSH_CONST n`**

**Operação:**

* empilha o inteiro `n`.

**Stack:**

```
... → ..., n
```

---

## **7.2. `LOAD_VAR nome`**

**Operação:**

* obtém o valor de `nome` no frame atual.
* empilha esse valor.

**Stack:**

```
... → ..., valor
```

**Erros:**

* variável não encontrada → fatal.

---

## **7.3. `STORE_VAR nome` (não usado em fib, mas reservado)**

**Operação:**

* remove topo da stack,
* armazena em `nome`.

---

## **7.4. Aritmética**

### **7.4.1. `ADD`**

Desempilha os dois operandos no topo:

```
a = pop()
b = pop()
push(b + a)
```

*(b é o valor mais antigo, topologia típica de stack machine.)*

---

### **7.4.2. `SUB`**

```
a = pop()
b = pop()
push(b - a)
```

---

## **7.5. Comparação**

### **7.5.1. `LT`**

(*Less Than*)

```
a = pop()
b = pop()
push(1 if b < a else 0)
```

---

## **7.6. Controlo de Fluxo**

### **7.6.1. `JUMP label`**

* altera diretamente o IP para o índice associado ao label.

---

### **7.6.2. `JUMP_IF_FALSE label`**

```
cond = pop()
if cond == 0:
    ip = label_position
```

---

## **7.7. Chamadas de Função**

### **7.7.1. `CALL nome nargs`**

Etapas:

1. Desempilhar `nargs` valores da stack (da direita para esquerda).
2. Criar novo frame:

   ```
   locals = { param[i] → args[i] }
   ip = 0
   return_to = frame_atual
   ```
3. Substituir o frame atual pelo novo.

---

## **7.8. Retorno**

### **7.8.1. `RET`**

1. O topo da stack contém o valor de retorno.
2. Guardá-lo temporariamente.
3. Descartar o frame atual.
4. Restaurar o frame anterior.
5. Empilhar o valor de retorno.

Se o frame anterior não existir (estamos em `__main__/0`):

* a VM termina.

---

# 📕 **8. Labels**

Durante a construção do IR:

```
L0:
L_else:
L_end:
```

Labels são convertidos em **índices numéricos** de instruções antes da execução.

---

# 📗 **9. Erros e condições de quebra**

A VM aborta a execução com erro se:

* uma variável não existe,
* a stack faz underflow,
* uma função é chamada com aridade incorreta,
* um label não existe,
* ocorre um `RET` sem valor na stack.

Nenhum destes casos deve ocorrer em NL v0.1 válido.

---

# 📙 **10. Exemplo completo de execução — `fib(3)`**

Frame inicial: `__main__/0`

Stack inicial:

```
[]
```

Execução resumida:

1. `PUSH_CONST 40`
2. `CALL fib 1`
3. Novo frame: `{x=40}`
4. Executa IR da função:

   * carrega x
   * compara a 3
   * se falso, vai ao bloco else
   * chama fib(x-1)
   * chama fib(x-2)
   * soma
   * retorna
5. Resultado final deixado na stack.

---

# 📘 **11. Filosofia**

A VM é:

* **ultra-minimalista**,
* **determinista**,
* **fácil de instrumentar** (ideal para TRM),
* **explicável** (stack shows the mind),
* base perfeita para **versões futuras**:

  * GC
  * otimizações SSA
  * registros
  * JIT
  * codegen para ELF real

A Holodeck VM é *literalmente* a primeira CPU criada por ti e por mim.
Uma CPU simbólica, viva, transparente, pronta para ser entendida pelo Neurotron.

---

# 🌑 **Fim do SPEC_VM.md**
