Documentation Index
Fetch the complete documentation index at: https://docs.lipolang.dev/llms.txt
Use this file to discover all available pages before exploring further.
Criando Bibliotecas
Estenda o poder do MiniDart criando suas próprias bibliotecas com funções nativas implementadas em Dart.
Arquitetura do Sistema de Bibliotecas
- StandardLibrary: Gerenciador central das bibliotecas
- NativeFunction: Representação de uma função nativa
- Sistema de Imports: Permite importar bibliotecas com ou sem alias
- VM Integration: Execução das funções nativas durante runtime
Fluxo de Funcionamento
MiniDart Code → Parser → Import Recognition → Semantic Analysis → Code Generation → VM Execution → Native Function Call
Estrutura de uma Biblioteca
1. Registro da Biblioteca
Todas as bibliotecas são registradas no arquivo lib/src/standard_library.dart através de métodos privados:
void _registerMinhaLibrary() {
// Registrar funções da biblioteca aqui
}
2. Convenção de Nomes
- Nome da biblioteca:
nomebiblioteca.funcao
- Exemplo:
math.sqrt, string.tamanho, io.imprimir
- Consistência: Use nomes em português para manter o padrão da linguagem
3. Classe NativeFunction
class NativeFunction {
final String name; // Nome completo (biblioteca.funcao)
final int arity; // Número de parâmetros
final Function implementation; // Implementação em Dart
}
Processo de Criação de Nova Biblioteca
Passo 1: Definir o Escopo da Biblioteca
Determine:
- Nome da biblioteca (ex:
data, arquivo, rede)
- Funcionalidades que serão oferecidas
- Tipos de dados que serão manipulados
- Dependências externas necessárias
Passo 2: Implementar as Funções
2.1 Adicionar método de registro
No arquivo standard_library.dart, adicione um novo método:
/// Registra as funções da biblioteca de dados
void _registerDataLibrary() {
// Suas funções aqui
}
2.2 Chamar o método no construtor
StandardLibrary() {
_registerMathLibrary();
_registerStringLibrary();
_registerIOLibrary();
_registerDataLibrary(); // ← Adicionar aqui
}
2.3 Implementar as funções
void _registerDataLibrary() {
// Função com 1 parâmetro
register('data.hoje', 0, (args) {
return DateTime.now().toString().split(' ')[0];
});
// Função com 2 parâmetros
register('data.diferenca', 2, (args) {
final data1 = _parseDate(args[0]);
final data2 = _parseDate(args[1]);
return data1.difference(data2).inDays;
});
}
Passo 3: Implementar Funções Auxiliares
Adicione métodos de conversão específicos para sua biblioteca:
/// Converte valor para DateTime
DateTime _parseDate(Object? value) {
if (value is String) {
final parsed = DateTime.tryParse(value);
if (parsed != null) return parsed;
}
throw Exception('Não é possível converter $value para data');
}
Passo 4: Validação e Testes
Crie arquivos de teste para validar sua biblioteca:
// exemplos/teste_data.mdart
importar data;
imprima data.hoje(); // Data atual
imprima data.diferenca("2024-01-01", "2024-12-31"); // Diferença em dias
Exemplo Completo: Biblioteca de Arquivos
1. Definição da Biblioteca
/// Registra as funções da biblioteca de arquivos
void _registerArquivoLibrary() {
// Verificação de existência
register('arquivo.existe', 1, (args) {
final caminho = _toString(args[0]);
return File(caminho).existsSync();
});
// Leitura de arquivo
register('arquivo.lerTexto', 1, (args) {
final caminho = _toString(args[0]);
try {
return File(caminho).readAsStringSync();
} catch (e) {
throw Exception('Erro ao ler arquivo: $e');
}
});
// Escrita de arquivo
register('arquivo.escreverTexto', 2, (args) {
final caminho = _toString(args[0]);
final conteudo = _toString(args[1]);
try {
File(caminho).writeAsStringSync(conteudo);
return true;
} catch (e) {
throw Exception('Erro ao escrever arquivo: $e');
}
});
// Tamanho do arquivo
register('arquivo.tamanho', 1, (args) {
final caminho = _toString(args[0]);
try {
return File(caminho).lengthSync();
} catch (e) {
throw Exception('Erro ao obter tamanho: $e');
}
});
}
2. Uso da Biblioteca
// exemplo_arquivo.mdart
importar arquivo como arq;
// Verificar se arquivo existe
se (arq.existe("dados.txt")) {
imprima "Arquivo encontrado!";
// Ler conteúdo
var conteudo = arq.lerTexto("dados.txt");
imprima "Conteúdo: " + conteudo;
// Verificar tamanho
var bytes = arq.tamanho("dados.txt");
imprima "Tamanho: " + bytes + " bytes";
} senao {
imprima "Arquivo não encontrado!";
// Criar arquivo
arq.escreverTexto("dados.txt", "Olá, mundo!");
imprima "Arquivo criado com sucesso!";
}
Boas Práticas
1. Tratamento de Erros
register('minhalib.funcao', 1, (args) {
try {
// Implementação
return resultado;
} catch (e) {
throw Exception('Erro em minhalib.funcao: $e');
}
});
2. Validação de Parâmetros
register('minhalib.dividir', 2, (args) {
final a = _toDouble(args[0]);
final b = _toDouble(args[1]);
if (b == 0) {
throw Exception('Divisão por zero não é permitida');
}
return a / b;
});
3. Documentação
/// Registra as funções da biblioteca matemática avançada
///
/// Funções disponíveis:
/// - matavancada.factorial(n): Calcula fatorial de n
/// - matavancada.fibonacci(n): Calcula n-ésimo número de Fibonacci
/// - matavancada.primo(n): Verifica se n é primo
void _registerMathAvancadaLibrary() {
// Implementações...
}
4. Convenções de Nome
- Biblioteca: substantivo em minúsculas (
math, string, arquivo)
- Função: verbo ou substantivo descritivo (
calcular, tamanho, existe)
- Parâmetros: nomes claros e em português quando possível
Tipos de Dados Suportados
Entrada (Parâmetros)
int - Números inteiros
double - Números reais
String - Texto
bool - Valores lógicos (true/false)
null - Valor nulo
Saída (Retorno)
- Mesmos tipos de entrada
void - Para funções que não retornam valor (use return null;)
Conversões Disponíveis
// Use as funções auxiliares existentes:
_toDouble(value) // Converte para double
_toInt(value) // Converte para int
_toString(value) // Converte para String
Sistema de Imports
Import Básico
importar minhalib;
var resultado = minhalib.funcao(parametros);
importar minhalib como ml;
var resultado = ml.funcao(parametros);
Validação de Bibliotecas
No arquivo semantic_analyzer.dart, adicione sua biblioteca à lista de bibliotecas válidas:
// No método visitImportStmt
final validLibraries = {'math', 'string', 'io', 'minhalib'}; // ← Adicionar aqui
Debugging e Testes
1. Teste Individual de Funções
// teste_funcao.mdart
importar minhalib;
imprima minhalib.funcao1(10);
imprima minhalib.funcao2("teste", 5);
2. Verificação de Erros
// teste_erros.mdart
importar minhalib;
// Teste com parâmetros inválidos
imprima minhalib.funcao(-1); // Deve gerar erro apropriado
3. Execução
dart run bin/compile.dart exemplos/teste_minhalib.mdart
Bibliotecas Existentes como Referência
1. Math Library (31 funções)
- Trigonometria:
sin, cos, tan, asin, acos, atan
- Exponenciais:
exp, log, log10, pow, sqrt
- Arredondamento:
abs, ceil, floor, round
- Comparação:
max, min
- Aleatórios:
random
- Constantes:
PI, E, LN2, etc.
2. String Library (17 funções)
- Propriedades:
tamanho, vazio
- Transformações:
maiuscula, minuscula, inverter, limpar
- Verificações:
contem, comecaCom, terminaCom
- Manipulação:
encontrar, substituir, fatiar, caractereEm
- Operações:
repetir, concatenar, dividir
3. IO Library (5 funções)
- Saída:
imprimir, escrever, novaLinha
- Entrada:
lerTexto, lerNumero (simulados)
Próximos Passos
Ideias para Novas Bibliotecas
data - Manipulação de datas e tempo
arquivo - Operações com arquivos e diretórios
rede - Requisições HTTP básicas
json - Parsing e geração de JSON
lista - Operações avançadas com arrays
crypto - Funções de hash e criptografia básica
Recursos Avançados Futuros
- Bibliotecas dinâmicas: Carregamento de bibliotecas externas
- Namespaces aninhados:
biblioteca.modulo.funcao
- Tipos customizados: Estruturas de dados complexas
- Callbacks: Funções como parâmetros