English · Português

Sintaxe Concreta (formas e exemplos)

Status: Stable · Evidência: aura/parser/to_ast.py, docs/language-reference/grammar.md, tests/test_parser_statements.py, tests/test_parser_expressions.py

Este documento mostra a forma concreta de cada construção com exemplos mínimos. As regras formais estão em grammar.md; os tokens estão em lexical-structure.md; o significado está nos documentos de domínio. Ele não repete — referencia.

Todo exemplo abaixo é a forma que o parser aceita (verificada por probe). Um programa executado com aura run deve declarar um def main() de nível superior; um arquivo de módulo não precisa de nenhum. Exemplos que parecem válidos mas não compilam estão listados em Anti-formas.


Programa mínimo

Um arquivo de entrada declara main. O runtime o invoca; nunca escreva uma chamada main() à direita (grammar.md §2; syntax.md).

def main() {
  print("Hello, world")
}

main não recebe parâmetros ou recebe um único parâmetro args; qualquer outra assinatura é E311, e a ausência de main em um arquivo de entrada é E310.


Variáveis e constantes

let name = "Alice"          // immutable
let mut counter = 0         // mutable
counter += 1
const PI = 3.14159          // must be initialised; never reassigned
const MAX: int = 100

let age: int = 30
let items: [int] = [1, 2, 3]

Desestruturação e atribuição múltipla usam padrões de tupla/lista, com um elemento rest opcional ...name:

let (a, b) = (1, 2)
let [first, ...rest] = [1, 2, 3, 4]
let x, y = 1, 2

Modificadores (public, private, protected, static, volatile, abstract) aparecem antes da keyword de declaração: private let x = 1, nunca let private x (grammar.md §3).


Tipos

int  float  str  bool  bytes  none       // primitives
[int]                                     // list
{str: int}                                // dict
{int}                                     // set
int | str                                 // union
str?                                      // optional
(int, int) -> int                         // function
{x: float, y: float}                      // structural
Box[int]                                  // type argument (brackets only)

Tipos são parseados para checagem/documentação e apagados em tempo de execução. A forma de colchete [T] é canônica; <T> foi removida (grammar.md §4).

Parâmetros e restrições de tipo:

class Box[T] {
  private let value: T

  public def get() -> T {
    return self.value
  }
}

def smallest[T: Comparable](items: [T]) -> T {
  return items[0]
}

Funções

def greet(name) -> str {
  return "Hello, " + name + "!"
}

def add(a: int, b: int) -> int {
  return a + b
}

def square(x: int) -> int = x * x     // expression body
def noop() { }                        // no return type

def configure(level, prefix = "[log]") { }   // default parameter
def sum_all(*numbers) -> int { return 0 }    // variadic positional
def log(level, **context) { }                // variadic keyword

O corpo é sempre um bloco com chaves ou um único = expr. def é a única keyword de função; fn, fun, function não existem. async def declara uma função async (grammar.md §3.2).


Lambdas

let double = x => x * 2
let square = (x) => x * x
let add = (a, b) => a + b
let none_ = () => 42
let block = (x) => {
  let doubled = x * 2
  return doubled + 1
}

Um parâmetro de lambda pode ser anotado: (x: int) => x * 2 (grammar.md §6.4).


Controle de fluxo

if temperature > 100 {
  print("Boiling!")
} else if temperature > 50 {
  print("Warm")
} else {
  print("Cold")
}

unless authenticated { redirect("/login") }

guard data != none else {
  print("No data")
  return
}

let label = condition ? "yes" : "no"     // ternary; `if` is also an expression

Loops

for i in range(10) { print(i) }
for item in items { print(item) }
for i in 0..<10 step 2 { print(i) }      // range with step

while count < 5 { count += 1 }
until ready { wait(100) }
loop { if quit() { break } }

outer: for i in range(10) {
  inner: for j in range(10) {
    if i * j > 20 { break outer }
  }
}

for usa a keyword in e um padrão. Labels funcionam com for, while, until e loop; break label / continue label onde tal loop não está em escopo é E318 (grammar.md §5.2; syntax.md1).


Pattern matching

match status {
  case 0 { print("inactive") }
  case 1 { print("active") }
  case n if n > 100 { print("overflow") }
  case _ { print("unknown") }
}

let text = match x {                 // match as an expression
  case 1 -> "one"
  case _ -> "other"
}

Padrões incluem literais, bindings, wildcard _, membros de enum pontuados (Color.RED), desestruturação de tupla/lista com *rest, padrões de construtor (Some(x)) e or-patterns (1 | 2). Um match sem case _ sobre um domínio finito avisa E109 (grammar.md §5.4; syntax.md2).


Enums

Membros são separados por vírgula (vírgula à direita é permitida). Valores são opcionais e autonumeram a partir do valor inteiro anterior.

enum Color { RED, GREEN, BLUE }

enum Status { Pending = "pending", Active = "active" }

let c = Color.RED            // access via dotted member
if status == Status.Active { process() }

Membros em linhas separadas sem vírgulas não parseiam: enum E { A B }Expected '}' but got 'B' (probe). Use vírgulas.


Classes

Header fields geram o construtor, um getter e (para mut) um setter. A visibilidade padrão é private; cada header field precisa de um tipo ou um default.

class User(name: str, mut age: int = 0, public id: int = 0) {
  public def greet() -> str {
    return "hi " + self.get_name()
  }
}

let u = User("ana", 30)       // Aura constructs with Type(args), no `new`
print(u.get_name())
u.set_age(31)

Campos de corpo e um construtor manual (não misture com um header):

class Point {
  public let x: int = 0
  public let y: int = 0

  public def new(x: int, y: int) {
    self.x = x
    self.y = y
  }

  public def distance() -> float {
    return (self.x ** 2 + self.y ** 2) ** 0.5
  }
}

Regras: todo membro precisa de uma visibilidade explícita (E307); membros devem ser únicos (E301); def new mapeia para __init__ do Python; uma classe tem exatamente um estilo de construtor. A herança usa apenas extends:

class Animal {
  protected let name: str = ""

  public def speak() -> str { return "..." }
}

class Dog extends Animal {
  public def speak() -> str { return self.name + " says woof" }
}

class Model extends django.db.models.Model { }   // dotted base allowed
class C extends A, B { }                          // multiple bases

class Dog(Animal) e implements não são Aura. A sobrescrita é implícita — não há override (grammar.md §3.3; classes.md).

Classes abstratas

abstract class Shape {
  public let name: str = "shape"

  public def describe() -> str { return "a " + self.name }
  public abstract def area() -> float
}

class Square extends Shape {
  public let side: float = 2.0
  public def area() -> float { return self.side * self.side }
}

abstract def não tem corpo; abstract antes de def dentro de um trait é erro de sintaxe (to_ast.py:1923-1928; classes.md).


Traits

trait Drawable {
  public def draw() -> void
  public def get_bounds() -> float
}

class Circle extends Drawable {
  private let radius: float = 0.0

  public def draw() -> void { print("circle") }
  public def get_bounds() -> float { return self.radius * 2 }
}

Um método de trait sem corpo já é abstrato — sem keyword abstract. Traits estendem com extends (grammar.md §3.4; classes.md (traits)).


Decorators

Decorators se anexam a um def ou a uma classe; um decorator em um campo é E320.

@staticmethod
public def max(a, b) -> int { return a }

class Rect {
  public @property
  def area() -> int { return 4 }

  public @classmethod
  def create(cls) { return cls() }
}

Modificadores de membro e decorators podem aparecer em qualquer ordem (@staticmethod public def fpublic @staticmethod def f).


Coleções

let list = [1, 2, 3]
let set = {1, 2, 3}
let dict = {name: "Alice", age: 30}
let pair = (1, "hello")
let single = (1,)
let empty = ()

print(list[0])          // index
print(list[-1])         // negative index
print(list[1:3])        // slice
print(list[::2])        // slice with step

let squares = [x * x for x in range(10)]
let evens = [x for x in range(20) if x % 2 == 0]
let lengths = {w: len(w) for w in words}
let gen = (x for x in xs)

Spread de lista e de dict:

let combined = [*list1, *list2, extra]
let merged = {**defaults, **overrides}

Chamadas e argumentos

f(a, b)                       // positional
f(name: "Alice", age: 30)     // keyword
f(*args)                      // positional spread
f(**kwargs)                   // keyword spread
f(a, *rest, **kw)             // mixed

Struct init é açúcar para uma chamada de construtor: um { após um identificador maiúsculo é um literal struct.

let p = Point{x: 1, y: 2}

Operadores

Precedência (menor para maior — grammar.md §6.1, correspondendo à tabela do parser to_ast.py:465-488):

Nível Operadores
1 =, +=, -=, *=, /=, %=, **=, &=, &#124;=, ^=, <<=, >>=, ??=, &#124;>
2 ? : (ternário)
3 or
4 and
5 == != < > <= >= in not in is is not
6 &#124;
7 ^
8 &
9 << >>
10 .. ..<
11 ?? ?:
12 + -
13 * / % as
14 **
15 unário - + ~ not await ...
16 call, index, slice, member, safe-nav, struct-init
let q = total / count                 // true division (never truncates)
let n = int(total / count)            // integer result via cast
let r = value as int                  // cast
let b = a ?? fallback                 // coalesce on none
let e = a ?: fallback                 // fallback on falsy
let c = user?.address?.city           // safe navigation
let i = list?[index]                  // safe index
let x = xs |> filter(f) |> map(g)     // pipe, left to right
let rng = 0..10                       // inclusive range
let rng2 = 0..<10                     // exclusive range
let open = 1..                        // infinite range

is / is not testam identidade; x is none é a checagem de nulo. Comparar um literal com is é rejeitado (to_ast.py:2567-2577).


Statements

return value
throw ValueError("bad")
break
continue
break outer
continue outer
yield
yield x + 1
spawn work()
assert x == 1, "message"

yield é em nível de statement, não parte de expression; yield x + 1 produz a soma inteira (grammar.md §6.1).


Blocos, with, erros

with open("f") as f {
  print(f)
}

async with client() as c { }      // __aenter__/__aexit__; only in async def

try {
  risky()
} catch TypeError {
  print("type")
} catch IOError as e {
  print(e)
} finally {
  cleanup()
}

let result = try { parse_int(s) } catch Error as e { 0 }   // try as expression

Uma cláusula catch tem exatamente um significado por grafia (syntax.md5):

Forma Significado
catch { } captura toda exceção (sem binding)
catch Type { } captura apenas Type
catch Type as e { } captura apenas Type, vincula a e
catch as e { } captura toda exceção, vincula a e

Um try exige pelo menos um catch ou um finally.


Imports

import stdlib.math                    // module; reach members by path
import stdlib.math as m               // alias
from stdlib.math import sqrt, PI      // names
from stdlib.math import sqrt as root  // name alias
import stdlib.math { sqrt, PI }       // brace form ≡ from ... import ...
from stdlib.math import *             // wildcard

A forma com chaves não pode ser combinada com as (syntax.md6).

Interop com Python

Um prefixo py. marca um módulo Python hospedeiro (_split_python_prefix, to_ast.py:494-505). O prefixo é removido antes da geração de código; o nome ligado é o último segmento do caminho.

import py.re                          // binds `re`
import py.os.path                     // binds `path`
from py.math import sqrt, pi as PI    // binds `sqrt` and `PI`

Um nome Python que colide com uma keyword de Aura deve ser aliasado; uma colisão nua é rejeitada (_reject_python_keyword_binding, to_ast.py:1832-1844):

from py.re import type as re_type     // ok: aliased
// from py.re import type             // error: 'type' is a reserved Aura keyword

Aliases de tipo e módulos

type UserId = int
type Point = {x: float, y: float}
type Pair[T] = [T]

module App.Services {
  export def public_function() -> int { return 42 }
  export const VERSION = "1.0.0"
  let mut cache = 0                   // private to the file
}

module Facade {
  export Components, Utils            // re-export from sibling files
}

Membros de módulo são privados ao arquivo declarante a menos que marcados export; export precede uma declaração nomeada ou introduz um re-export (grammar.md §3.7; modules.md).


Anti-formas (NÃO compila)

Cada grafia rejeitada, com o erro apontado do parser e sua substituição canônica:

fn f() { }                  // ❌ 'fn' is not part of Aura; use 'def' instead
fun f() { }                 // ❌ 'fun' is not part of Aura; use 'def'
function f() { }            // ❌ 'function' is not part of Aura; use 'def'
let f = lambda x: x         // ❌ 'lambda' is not part of Aura; use '(x) => expr'
let c = new C()             // ❌ 'new' is not part of Aura; construct with 'Type(args)'
var x = 1                   // ❌ 'var' is not part of Aura; use 'let mut' or 'let'
foreach x in xs { }         // ❌ 'foreach' is not part of Aura; use 'for x in xs'
repeat { }                  // ❌ 'repeat' is not part of Aura; use 'loop { }' or 'until'
do { }                      // ❌ 'do' is not part of Aura; use 'loop { }' with 'break'
switch x { }                // ❌ 'switch' is not part of Aura; use 'match x { case ... }'
if a { } elif b { }         // ❌ 'elif' is not part of Aura; write 'else if'
if a { } elsif b { }        // ❌ 'elsif' is not part of Aura; write 'else if'
let x = null                // ❌ 'null' is not part of Aura; use 'none'
let x = !y                  // ❌ '!' is not part of Aura; use 'not'
let x = a && b              // ❌ '&&' is not part of Aura; use 'and'
let x = a || b              // ❌ '||' is not part of Aura; use 'or'
match x { case 1: f() }     // ❌ ':' is not Aura case syntax; write 'case 1 -> ...'
match x { case 1 => 1 }     // ❌ '=>' is not Aura case syntax; write 'case 1 -> ...'
class C(A) { }              // ❌ parenthesised base; write 'class C extends A'
class C implements D { }    // ❌ 'implements' is not Aura; use 'extends'
class Box<T> { }            // ❌ type parameters use brackets: 'Box[T]'
if x is "a" { }             // ❌ 'is' compares identity; use '=='
enum E { A B }              // ❌ members are comma-separated: 'enum E { A, B }'

Anti-formas de outras linguagens (NÃO existe)

NÃO escreva Escreva em vez disso Evidência
fn, fun, function def to_ast.py:816-818, 2647-2649
elif, elsif else if to_ast.py:819-822
var (statement) let mut / let to_ast.py:791, 801-804
foreach for x in xs to_ast.py:792
lambda (x) => expr to_ast.py:795, 2650-2653
new Type(args) to_ast.py:796, 2640-2646
repeat loop { } / until to_ast.py:797
switch match x { case ... -> ... } to_ast.py:798
do loop { } with break to_ast.py:799
null none to_ast.py:2637-2639
True / False / None true / false / none to_ast.py:533-537
!x not x to_ast.py:2435-2437
&& / &#124;&#124; and / or to_ast.py:2497-2502
case x: / case x => case x -> to_ast.py:2310-2317
class C(A) class C extends A to_ast.py:1270
implements extends to_ast.py:1887-1891
Box<T> Box[T] to_ast.py:1112
volatily volatile to_ast.py:281-284
a ? b : c is valid; x is <literal> == / != to_ast.py:2567-2577