Skip to content

Commit

Permalink
Merge pull request #12 from kassane/new-chapters
Browse files Browse the repository at this point in the history
Add New chapters: Dub and byExample (translated)
  • Loading branch information
sergiors authored Feb 21, 2024
2 parents 6b561ea + f4aa4e3 commit 9ef2d86
Show file tree
Hide file tree
Showing 12 changed files with 395 additions and 0 deletions.
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

0 comments on commit 9ef2d86

Please sign in to comment.