Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add New chapters: Dub and byExample (translated) #12

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions byexample/code-generation-parser.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Gerador de código (Parser)

Neste exemplo, um parser de configuração é gerado em tempo de compilação.
Vamos supor que nosso programa tenha algumas opções de configuração,
resumidas em uma `struct` de configurações:

```d
struct Config
{
int runs, port;
string name;
}
```

Embora escrever um parser para essa estrutura não seja difícil, teríamos que
atualizar constantemente o parser, sempre que modificarmos o objeto `Config`.
Por isso, estamos interessados em escrever uma função `parse` genérica que possa
ler opções de configuração arbitrárias. Para simplificar, `parse` aceitará
um formato muito simples de opções de configuração `key1=value1,key2=value2`, mas a mesma técnica
pode ser usada para qualquer formato de configuração arbitrário. Para muitos formatos de configuração
formatos de configuração populares, é claro, já existem soluções prontas de outros parsers no [registro do DUB](https://code.dlang.org).

Configuração de leitura
-------------------------

Vamos supor que o usuário tenha __"name=dlang,port=8080"__ como uma string de configuração.
Em seguida, dividimos diretamente as opções de configuração por vírgula e chamamos `parse` para cada definição de configuração, individualmente.
Depois que todas as opções de configurações tiverem sido analisadas, todo o objeto de configuração será exibido.

Análise
-----

O `parse` é onde a verdadeira mágica acontece, mas primeiro dividimos a opção de configuração fornecida (por exemplo, "name=dlang") por "=" em chave ("name") e valor ("dlang").
A instrução `switch` é executada com a chave analisada, mas o mais interessante é que
os casos de `switch` foram gerados estaticamente. O `c.tupleof` retorna uma lista de todos os membros no formato `(idx, name)`. O compilador detecta que o `c.tupleof` é conhecido em tempo de compilação e desenrolará o loop foreach em tempo de compilação.
Portanto, `Conf.tupleof[idx].stringof` produzirá os membros individuais do objeto struct
e gerará uma instrução de caso para cada membro.

Da mesma forma, enquanto estiver no loop estático, os membros individuais podem ser acessados pelo índice:
`c.tupleof[idx]` e, assim, podemos atribuir ao respectivo membro o valor analisado da
string de configuração fornecida. Além disso, `dropOne` é necessário, pois o `range` dividido ainda aponta para a chave e, portanto, `dropOne.front` retornará o segundo elemento.
Além disso, `to!(typeof(field))` fará a análise real da string de entrada
para o respectivo tipo do membro da estrutura de configuração.
Por fim, como o loop `foreach` é executado em tempo de compilação, um `break` interromperia esse loop.

Entretanto, depois que uma opção de configuração for analisada com sucesso, não queremos pular para o próximo caso na instrução `switch` e, portanto, um `break` é utilizado para interromper a instrução `switch`.

## {SourceCode}

```d
import std.algorithm, std.conv, std.range,
std.stdio, std.traits;
struct Config
{
int runs, port;
string name;
}
void main()
{
Config conf;
// use o parser gerado a
// cada entrada
"runs=1,port=2,name=hello"
.splitter(",")
.each!(e => conf.parse(e));
conf.writeln;
}
void parse(Conf)(ref Conf c, string entry)
{
auto r = entry.splitter("=");
auto key = r.front, value = r.dropOne.front;
`Switch`: `switch` (key)
{
static foreach(idx, field; Conf.tupleof)
{
case field.stringof:
c.tupleof[idx] =
value.to!(typeof(field));
break `Switch`;
}
default:
assert (0, "Unknown member name.");
}
}
```
3 changes: 3 additions & 0 deletions byexample/index.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: Exemplos feito em D
ordering:
- code-generation-parser
20 changes: 20 additions & 0 deletions dub/emsi_containers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# EMSI Containers

Experimente [emsi_containers](https://github.com/dlang-community/containers)

## {SourceCode:incomplete}

```d
/+dub.sdl:
dependency "emsi_containers" version="~>0.7"
+/
import std.stdio;
void main(string[] args)
{
import containers;
DynamicArray!int arr;
arr ~= 1;
foreach (e; arr)
e.writeln;
}
```
10 changes: 10 additions & 0 deletions dub/index.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
title: Pacotes DUB
ordering:
- mir-algorithm
- mir-random
- mir
- emsi_containers
- vibe-d
- libdparse
- pegged
- lubeck
44 changes: 44 additions & 0 deletions dub/libdparse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# libdparse

Experimente [libdparse](https://github.com/dlang-community/libdparse)

## {SourceCode:fullWidth:incomplete}

```d
/+dub.sdl:
dependency "libdparse" version="~>0.10"
+/
import dparse.ast;
import std.stdio;

class TestVisitor : ASTVisitor
{
alias visit = ASTVisitor.visit;

override void visit(const FunctionDeclaration decl)
{
decl.name.text.writeln;
}
}

void main()
{
import dparse.lexer;
import dparse.parser : parseModule;
import dparse.rollback_allocator : RollbackAllocator;
import std.array : array;
import std.string : representation;

auto sourceCode = q{
void foo() @safe {}
}.dup;
LexerConfig config;
auto cache = StringCache(StringCache.defaultBucketCount);
auto tokens = getTokensForParser(sourceCode.representation, config, &cache);

RollbackAllocator rba;
auto m = parseModule(tokens.array, "test.d", &rba);
auto visitor = new TestVisitor();
visitor.visit(m);
}
```
42 changes: 42 additions & 0 deletions dub/lubeck.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Lubeck

Biblioteca de álgebra linear de alto nível baseada em CBLAS, LAPACK e Mir Algorithm.

## Dependências

O Lubeck depende do CBLAS e da API do LAPACK. Talvez seja necessário instalá-los e atualizar o `dub.sdl`.
O CBLAS e o LAPACK são pré-instalados no MacOS.
Os backends [OpenBLAS](http://www.openblas.net) ou [Intel MKL](https://software.intel.com/en-us/mkl) são recomendados para Linux e Windows.

## Links

- [GitHub](https://github.com/kaleidicassociates/lubeck)
- [Mir Algorithm API](http://mir-algorithm.libmir.org)
- [Mir Random API](http://mir-random.libmir.org)
- [Mir API](http://mir.libmir.org)

## {SourceCode:incomplete}

```d
/+dub.sdl:
dependency "lubeck" version="~>1.1"
+/
import kaleidic.lubeck: mtimes;
import mir.algorithm.iteration: each;
import mir.ndslice: magic, repeat, as,
slice, byDim;
import std.stdio: writeln;

void main()
{
auto n = 5;
// Magic Square
auto matrix = n.magic.as!double.slice;
// [1 1 1 1 1]
auto vec = 1.repeat(n).as!double.slice;
// Uses CBLAS for multiplication
matrix.mtimes(vec).writeln;
"-----".writeln;
matrix.mtimes(matrix).byDim!0.each!writeln;
}
```
38 changes: 38 additions & 0 deletions dub/mir-algorithm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Mir Algorithm

Biblioteca principal para cálculos e uma base para o pacote de arrays multidimensionais - ndslice (equivalente ao numpy).

## Links

- [API Documentation](http://mir-algorithm.libmir.org)
- [GitHub](https://github.com/libmir/mir-algorithm)
- [Lubeck](https://github.com/kaleidicassociates/lubeck) - Linear Algebra Library based on NDSlice API.

## Maiores detalhes

[Magic Square on Wikipedia](https://en.wikipedia.org/wiki/Magic_square).

## {SourceCode}

```d
/+dub.sdl:
dependency "mir-algorithm" version="~>3.6"
+/
import mir.algorithm.iteration: each;
import mir.ndslice;
import std.stdio: writeln;

void main()
{
auto matrix = slice!double(3, 4);
matrix[] = 0;
matrix.diagonal[] = 1;

auto row = matrix[2];
row[3] = 6;
// D & C index order
assert(matrix[2, 3] == 6);

matrix.byDim!0.each!writeln;
}
```
30 changes: 30 additions & 0 deletions dub/mir-random.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Mir Random

Gerador de números aleatórios avançado.

## Links

- [API Documentation](http://mir-random.libmir.org)
- [GitHub](https://github.com/libmir/mir-random)
- [Mir Algorithm Documentation](http://mir-algorithm.libmir.org)

## {SourceCode}

```d
/+dub.sdl:
dependency "mir-random" version="~>2.2"
+/
import mir.random;
import mir.random.algorithm: randomSlice;
import mir.random.variable: normalVar;
import std.stdio: writeln;

void main()
{
auto sample = normalVar.randomSlice(10);
writeln(sample);

// prints random element from the sample
writeln(sample[$.randIndex]);
}
```
42 changes: 42 additions & 0 deletions dub/mir.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Mir

Este pacote inclui:

- [mir-algorithm package](dub/mir-algorithm)- Biblioteca principal para cálculos e uma base para o pacote de arrays multidimensionais - ndslice (equivalente ao numpy).
- [mir-random package](dub/mir-random) - Geradores de números aleatórios avançados.
- Tensores esparsos
- Hoffman

## Links

- [Mir Algorithm API](http://mir-algorithm.libmir.org)
- [Mir Random API](http://mir-random.libmir.org)
- [Mir API](http://mir.libmir.org)
- [GitHub](https://github.com/libmir/mir)
- [Lubeck](https://github.com/kaleidicassociates/lubeck) - Linear Algebra Library based on NDSlice API.

## {SourceCode}

```d
/+dub.sdl:
dependency "mir" version="~>3.2"
+/
import mir.sparse;
import std.stdio: writeln;

void main()
{
// DOK format
auto sl = sparse!double(5, 8);
sl[] =
[[0, 2, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 4],
[0, 0, 0, 0, 0, 0, 0, 0],
[6, 0, 0, 0, 0, 0, 0, 9],
[0, 0, 0, 0, 0, 0, 0, 5]];

// CRS/CSR format
auto crs = sl.compress;
writeln(crs);
}
```
53 changes: 53 additions & 0 deletions dub/pegged.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Pegged

O Pegged é um parser gerador (PEG - parsing expression grammar).

A partir dessa definição de gramática, será criado um conjunto de analisadores relacionados,
para serem usados em tempo de execução ou de compilação.

## Maiores detalhes

- [Pegged on GitHub](https://github.com/PhilippeSigaud/Pegged)
- [Reference article for Pegged's syntax](http://bford.info/pub/lang/peg)

## {SourceCode:fullWidth:incomplete}

```d
/+dub.sdl:
dependency "pegged" version="~>0.4"
+/
import pegged.grammar;
import std.stdio;

mixin(grammar(`
Arithmetic:
Term < Factor (Add / Sub)*
Add < "+" Factor
Sub < "-" Factor
Factor < Primary (Mul / Div)*
Mul < "*" Primary
Div < "/" Primary
Primary < Parens / Neg / Pos / Number / Variable
Parens < "(" Term ")"
Neg < "-" Primary
Pos < "+" Primary
Number < ~([0-9]+)

Variable <- identifier
`));

void main()
{
// Parsing at compile-time:
enum parseTree1 = Arithmetic("1 + 2 - (3*x-5)*6");

pragma(msg, parseTree1.matches);
assert(parseTree1.matches == ["1", "+", "2", "-",
"(", "3", "*", "x", "-", "5", ")", "*", "6"]);
writeln(parseTree1);

// And at runtime too:
auto parseTree2 = Arithmetic(" 0 + 123 - 456 ");
assert(parseTree2.matches == ["0", "+", "123", "-", "456"]);
}
```
Loading
Loading