c2r 1.0.0__tar.gz → 1.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {c2r-1.0.0 → c2r-1.0.2}/.idea/misc.xml +3 -0
- c2r-1.0.2/ANALYSIS_REPORT_PT.md +60 -0
- {c2r-1.0.0 → c2r-1.0.2}/Cargo.lock +44 -66
- {c2r-1.0.0 → c2r-1.0.2}/Cargo.toml +3 -1
- {c2r-1.0.0 → c2r-1.0.2}/PKG-INFO +2 -2
- c2r-1.0.2/ROADMAP_PROXIMOS_PASSOS.md +54 -0
- {c2r-1.0.0 → c2r-1.0.2}/c2r/cli.py +74 -1
- c2r-1.0.2/docs/architecture.md +55 -0
- c2r-1.0.2/docs/limitations.md +33 -0
- c2r-1.0.2/docs/migration_example.md +86 -0
- c2r-1.0.2/docs/safety_policy.md +44 -0
- c2r-1.0.2/legacy_cpp_project/code.cpp +74 -0
- {c2r-1.0.0 → c2r-1.0.2}/pyproject.toml +2 -2
- c2r-1.0.2/reproduce_issue.py +76 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/mod.rs +2 -1
- c2r-1.0.2/src/analysis/stl_registry.rs +36 -0
- c2r-1.0.2/src/analyzer.rs +729 -0
- c2r-1.0.2/src/clang_frontend_mock.rs +60 -0
- c2r-1.0.2/src/cpp_parser.rs +381 -0
- c2r-1.0.2/src/formatter.rs +44 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/lib.rs +14 -7
- {c2r-1.0.0 → c2r-1.0.2}/src/piir.rs +63 -0
- c2r-1.0.2/test_exception +0 -0
- c2r-1.0.2/tests/cpp_samples/07_complex_semantic.cpp +74 -0
- c2r-1.0.2/tests/cpp_samples/08_exceptions.cpp +11 -0
- c2r-1.0.2/tests/golden/07_complex_semantic.rs +47 -0
- c2r-1.0.2/tests/run_golden.py +73 -0
- c2r-1.0.2/user_test_case.py +106 -0
- c2r-1.0.0/src/analyzer.rs +0 -321
- c2r-1.0.0/src/clang_frontend_mock.rs +0 -68
- c2r-1.0.0/src/cpp_parser.rs +0 -112
- {c2r-1.0.0 → c2r-1.0.2}/.gitignore +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/.idea/.gitignore +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/.idea/c2r.iml +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/.idea/modules.xml +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/.idea/vcs.xml +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/README.md +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/benches/run_bench.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/c2r/__init__.py +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/docs/SPECIFICATION_PT.md +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/run_demo.py +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/andersen.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/cycles.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/oo_mapper.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/regions.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/split_tree.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/steensgaard.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/thread_safety.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/analysis/traits.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/bench_harness.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/src/disjoint_set.rs +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/temp_cpp_check/src/main.cpp +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/temp_cpp_check/src/math/vector.h +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/tests/cpp_samples/01_basic_box.cpp +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/tests/cpp_samples/02_leak.cpp +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/tests/cpp_samples/03_double_free.cpp +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/tests/cpp_samples/04_aliasing.cpp +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/tests/cpp_samples/05_doubly_linked_list.cpp +0 -0
- {c2r-1.0.0 → c2r-1.0.2}/tests/cpp_samples/06_threads.cpp +0 -0
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<project version="4">
|
|
3
|
+
<component name="Black">
|
|
4
|
+
<option name="sdkName" value="Python 3.11" />
|
|
5
|
+
</component>
|
|
3
6
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
|
4
7
|
</project>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Relatório Técnico: Análise de Falhas na Transpilação C++ para Rust
|
|
2
|
+
|
|
3
|
+
## 1. Resumo Executivo
|
|
4
|
+
A análise confirmou que o comportamento observado ("Problemas graves no código gerado") é causado pela natureza **simulada** (mock) do front-end de análise do projeto. O transpiler atual não realiza uma análise semântica completa do código C++ arbitrário; em vez disso, ele detecta padrões de strings específicos (como `"class ResourceManager"`) e emite uma sequência predefinida de eventos que resulta em um código Rust hardcoded e incompleto.
|
|
5
|
+
|
|
6
|
+
## 2. Diagnóstico Detalhado
|
|
7
|
+
|
|
8
|
+
### 2.1. Causa Raiz: Front-end Simulado
|
|
9
|
+
O arquivo `src/clang_frontend_mock.rs` contém a lógica de ingestão. Ele não possui um parser C++ real capaz de entender classes, métodos ou lambdas complexos.
|
|
10
|
+
|
|
11
|
+
Ao encontrar a string `"class ResourceManager"`, o sistema ativa um bloco de código rígido (linhas 31-77 do arquivo mencionado) que retorna uma lista fixa de eventos (`LifeEvent`).
|
|
12
|
+
|
|
13
|
+
**Evidência (`src/clang_frontend_mock.rs`):**
|
|
14
|
+
```rust
|
|
15
|
+
if source.contains("class ResourceManager") {
|
|
16
|
+
info!("Frontend: Detected 'Complex Semantic' test case.");
|
|
17
|
+
// ... define IDs fixos 200, 201, ...
|
|
18
|
+
return vec![
|
|
19
|
+
// ... Eventos hardcoded ...
|
|
20
|
+
LifeEvent::Constant { target: result_var, value: "60".into(), ... },
|
|
21
|
+
// ...
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2.2. Falhas Específicas Reportadas
|
|
27
|
+
|
|
28
|
+
#### A. `ResourceManager` virou `Arc<Mutex<0>>`
|
|
29
|
+
* **Observação:** O código gerado ignora a estrutura interna (`HashMap`).
|
|
30
|
+
* **Causa:** O analisador (`src/analyzer.rs`) trata alocações compartilhadas (`shared_mutable_vars`) de forma genérica. Quando vê uma alocação para o ID 200 (manager), ele gera `Arc::new(Mutex::new(0))` porque não há lógica para converter a definição da classe C++ em uma struct Rust equivalente neste fluxo específico.
|
|
31
|
+
|
|
32
|
+
#### B. Valores Iniciais Ignorados e Resultado Hardcoded
|
|
33
|
+
* **Observação:** `let result = 60;` aparece do nada.
|
|
34
|
+
* **Causa:** O evento `LifeEvent::Constant` com valor "60" é inserido explicitamente pelo mock. O cálculo real (10+20+30) nunca é realizado ou traduzido.
|
|
35
|
+
|
|
36
|
+
#### C. Thread Vazia
|
|
37
|
+
* **Observação:** `std::thread::spawn(move || {});`
|
|
38
|
+
* **Causa:** O analisador (`src/analyzer.rs`) tem uma lógica específica para o ID 200 dentro de eventos de mutação.
|
|
39
|
+
```rust
|
|
40
|
+
// src/analyzer.rs
|
|
41
|
+
if target.0 == 200 {
|
|
42
|
+
self.push_code(quote! {
|
|
43
|
+
// manager.increment_all();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
Isso gera apenas um comentário (que pode ter sido removido ou não visível dependendo do contexto da thread), e não o loop `for` original.
|
|
48
|
+
|
|
49
|
+
#### D. Lambda Destruída
|
|
50
|
+
* **Observação:** `println!("{:?}", r1)` em vez da lógica customizada.
|
|
51
|
+
* **Causa:** A lógica da lambda não é parseada. O mock apenas emite um evento `IOPrint` genérico para simular uma saída, e o `Analyzer` usa formatação de debug `{:?}` para tipos ponteiro (`Arc`).
|
|
52
|
+
|
|
53
|
+
## 3. Validação da Solução Proposta
|
|
54
|
+
A versão Rust fornecida pelo usuário ("Tradução correta") representa a implementação ideal e idiomática. Para que a ferramenta gerasse esse código automaticamente, seria necessário:
|
|
55
|
+
1. **Parser Real:** Substituir o `ClangFrontendMock` por um parser baseada em `libclang` ou `tree-sitter` que gere uma AST completa.
|
|
56
|
+
2. **Mapeamento de Tipos:** Suporte real para `std::unordered_map` -> `HashMap` e `std::mutex` -> `Mutex`.
|
|
57
|
+
3. **Análise de Fluxo:** Capacidade de traduzir loops e corpos de funções, em vez de apenas sequências lineares de eventos.
|
|
58
|
+
|
|
59
|
+
## 4. Conclusão
|
|
60
|
+
A ferramenta, em seu estado atual, opera como um protótipo demonstrativo ("Smoke and Mirrors") para casos de teste específicos. As falhas reportadas não são bugs de uma lógica complexa, mas limitações intencionais de um sistema que ainda não implementa a transpilação generalizada de C++.
|
|
@@ -67,12 +67,6 @@ version = "1.5.0"
|
|
|
67
67
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
68
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
69
69
|
|
|
70
|
-
[[package]]
|
|
71
|
-
name = "bitflags"
|
|
72
|
-
version = "2.10.0"
|
|
73
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
74
|
-
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
|
75
|
-
|
|
76
70
|
[[package]]
|
|
77
71
|
name = "c2r_core"
|
|
78
72
|
version = "1.0.0"
|
|
@@ -83,6 +77,8 @@ dependencies = [
|
|
|
83
77
|
"pyo3",
|
|
84
78
|
"quote",
|
|
85
79
|
"regex",
|
|
80
|
+
"serde",
|
|
81
|
+
"serde_json",
|
|
86
82
|
"syn",
|
|
87
83
|
]
|
|
88
84
|
|
|
@@ -123,9 +119,9 @@ dependencies = [
|
|
|
123
119
|
|
|
124
120
|
[[package]]
|
|
125
121
|
name = "heck"
|
|
126
|
-
version = "0.
|
|
122
|
+
version = "0.5.0"
|
|
127
123
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
128
|
-
checksum = "
|
|
124
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
129
125
|
|
|
130
126
|
[[package]]
|
|
131
127
|
name = "indoc"
|
|
@@ -142,6 +138,12 @@ version = "1.70.2"
|
|
|
142
138
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
143
139
|
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
|
144
140
|
|
|
141
|
+
[[package]]
|
|
142
|
+
name = "itoa"
|
|
143
|
+
version = "1.0.17"
|
|
144
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
145
|
+
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
|
146
|
+
|
|
145
147
|
[[package]]
|
|
146
148
|
name = "jiff"
|
|
147
149
|
version = "0.2.18"
|
|
@@ -172,15 +174,6 @@ version = "0.2.180"
|
|
|
172
174
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
173
175
|
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
|
174
176
|
|
|
175
|
-
[[package]]
|
|
176
|
-
name = "lock_api"
|
|
177
|
-
version = "0.4.14"
|
|
178
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
179
|
-
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
|
180
|
-
dependencies = [
|
|
181
|
-
"scopeguard",
|
|
182
|
-
]
|
|
183
|
-
|
|
184
177
|
[[package]]
|
|
185
178
|
name = "log"
|
|
186
179
|
version = "0.4.29"
|
|
@@ -214,29 +207,6 @@ version = "1.70.2"
|
|
|
214
207
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
215
208
|
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
216
209
|
|
|
217
|
-
[[package]]
|
|
218
|
-
name = "parking_lot"
|
|
219
|
-
version = "0.12.5"
|
|
220
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
221
|
-
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
|
222
|
-
dependencies = [
|
|
223
|
-
"lock_api",
|
|
224
|
-
"parking_lot_core",
|
|
225
|
-
]
|
|
226
|
-
|
|
227
|
-
[[package]]
|
|
228
|
-
name = "parking_lot_core"
|
|
229
|
-
version = "0.9.12"
|
|
230
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
231
|
-
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
|
232
|
-
dependencies = [
|
|
233
|
-
"cfg-if",
|
|
234
|
-
"libc",
|
|
235
|
-
"redox_syscall",
|
|
236
|
-
"smallvec",
|
|
237
|
-
"windows-link",
|
|
238
|
-
]
|
|
239
|
-
|
|
240
210
|
[[package]]
|
|
241
211
|
name = "portable-atomic"
|
|
242
212
|
version = "1.13.0"
|
|
@@ -263,15 +233,15 @@ dependencies = [
|
|
|
263
233
|
|
|
264
234
|
[[package]]
|
|
265
235
|
name = "pyo3"
|
|
266
|
-
version = "0.
|
|
236
|
+
version = "0.23.5"
|
|
267
237
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
268
|
-
checksum = "
|
|
238
|
+
checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872"
|
|
269
239
|
dependencies = [
|
|
270
240
|
"cfg-if",
|
|
271
241
|
"indoc",
|
|
272
242
|
"libc",
|
|
273
243
|
"memoffset",
|
|
274
|
-
"
|
|
244
|
+
"once_cell",
|
|
275
245
|
"portable-atomic",
|
|
276
246
|
"pyo3-build-config",
|
|
277
247
|
"pyo3-ffi",
|
|
@@ -281,9 +251,9 @@ dependencies = [
|
|
|
281
251
|
|
|
282
252
|
[[package]]
|
|
283
253
|
name = "pyo3-build-config"
|
|
284
|
-
version = "0.
|
|
254
|
+
version = "0.23.5"
|
|
285
255
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
286
|
-
checksum = "
|
|
256
|
+
checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb"
|
|
287
257
|
dependencies = [
|
|
288
258
|
"once_cell",
|
|
289
259
|
"target-lexicon",
|
|
@@ -291,9 +261,9 @@ dependencies = [
|
|
|
291
261
|
|
|
292
262
|
[[package]]
|
|
293
263
|
name = "pyo3-ffi"
|
|
294
|
-
version = "0.
|
|
264
|
+
version = "0.23.5"
|
|
295
265
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
296
|
-
checksum = "
|
|
266
|
+
checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d"
|
|
297
267
|
dependencies = [
|
|
298
268
|
"libc",
|
|
299
269
|
"pyo3-build-config",
|
|
@@ -301,9 +271,9 @@ dependencies = [
|
|
|
301
271
|
|
|
302
272
|
[[package]]
|
|
303
273
|
name = "pyo3-macros"
|
|
304
|
-
version = "0.
|
|
274
|
+
version = "0.23.5"
|
|
305
275
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
306
|
-
checksum = "
|
|
276
|
+
checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da"
|
|
307
277
|
dependencies = [
|
|
308
278
|
"proc-macro2",
|
|
309
279
|
"pyo3-macros-backend",
|
|
@@ -313,9 +283,9 @@ dependencies = [
|
|
|
313
283
|
|
|
314
284
|
[[package]]
|
|
315
285
|
name = "pyo3-macros-backend"
|
|
316
|
-
version = "0.
|
|
286
|
+
version = "0.23.5"
|
|
317
287
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
318
|
-
checksum = "
|
|
288
|
+
checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028"
|
|
319
289
|
dependencies = [
|
|
320
290
|
"heck",
|
|
321
291
|
"proc-macro2",
|
|
@@ -333,15 +303,6 @@ dependencies = [
|
|
|
333
303
|
"proc-macro2",
|
|
334
304
|
]
|
|
335
305
|
|
|
336
|
-
[[package]]
|
|
337
|
-
name = "redox_syscall"
|
|
338
|
-
version = "0.5.18"
|
|
339
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
340
|
-
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
|
341
|
-
dependencies = [
|
|
342
|
-
"bitflags",
|
|
343
|
-
]
|
|
344
|
-
|
|
345
306
|
[[package]]
|
|
346
307
|
name = "regex"
|
|
347
308
|
version = "1.12.2"
|
|
@@ -378,10 +339,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
378
339
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
379
340
|
|
|
380
341
|
[[package]]
|
|
381
|
-
name = "
|
|
382
|
-
version = "1.
|
|
342
|
+
name = "serde"
|
|
343
|
+
version = "1.0.228"
|
|
383
344
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
384
|
-
checksum = "
|
|
345
|
+
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
|
346
|
+
dependencies = [
|
|
347
|
+
"serde_core",
|
|
348
|
+
"serde_derive",
|
|
349
|
+
]
|
|
385
350
|
|
|
386
351
|
[[package]]
|
|
387
352
|
name = "serde_core"
|
|
@@ -404,10 +369,17 @@ dependencies = [
|
|
|
404
369
|
]
|
|
405
370
|
|
|
406
371
|
[[package]]
|
|
407
|
-
name = "
|
|
408
|
-
version = "1.
|
|
372
|
+
name = "serde_json"
|
|
373
|
+
version = "1.0.149"
|
|
409
374
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
410
|
-
checksum = "
|
|
375
|
+
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
|
376
|
+
dependencies = [
|
|
377
|
+
"itoa",
|
|
378
|
+
"memchr",
|
|
379
|
+
"serde",
|
|
380
|
+
"serde_core",
|
|
381
|
+
"zmij",
|
|
382
|
+
]
|
|
411
383
|
|
|
412
384
|
[[package]]
|
|
413
385
|
name = "syn"
|
|
@@ -458,3 +430,9 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
|
|
458
430
|
dependencies = [
|
|
459
431
|
"windows-link",
|
|
460
432
|
]
|
|
433
|
+
|
|
434
|
+
[[package]]
|
|
435
|
+
name = "zmij"
|
|
436
|
+
version = "1.0.19"
|
|
437
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
438
|
+
checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
|
|
@@ -12,13 +12,15 @@ name = "c2r_core"
|
|
|
12
12
|
crate-type = ["cdylib", "rlib"]
|
|
13
13
|
|
|
14
14
|
[dependencies]
|
|
15
|
-
pyo3 = { version = "0.
|
|
15
|
+
pyo3 = { version = "0.23", features = ["extension-module"] }
|
|
16
16
|
regex = "1.10"
|
|
17
17
|
log = "0.4"
|
|
18
18
|
env_logger = "0.11"
|
|
19
19
|
syn = { version = "2.0", features = ["full", "extra-traits"] }
|
|
20
20
|
quote = "1.0"
|
|
21
21
|
proc-macro2 = "1.0"
|
|
22
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
23
|
+
serde_json = "1.0"
|
|
22
24
|
|
|
23
25
|
[[bin]]
|
|
24
26
|
name = "bench_runner"
|
{c2r-1.0.0 → c2r-1.0.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: c2r
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -13,7 +13,7 @@ Requires-Dist: click
|
|
|
13
13
|
Summary: Deterministic C++ to Rust Transpiler with Industrial-Grade Static Analysis
|
|
14
14
|
Author-email: Ferrum Team <dev@ferrum.io>
|
|
15
15
|
License: MIT
|
|
16
|
-
Requires-Python: >=3.8
|
|
16
|
+
Requires-Python: >=3.8, <3.13
|
|
17
17
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
18
18
|
|
|
19
19
|
# c2r: The Industrial C++ to Rust Transpiler
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Roadmap: Próximos Passos para a Evolução do Transpiler
|
|
2
|
+
|
|
3
|
+
Este documento descreve o caminho técnico necessário para evoluir o projeto de um protótipo experimental (baseado em Regex e Mock) para uma ferramenta robusta de transpilação C++ para Rust.
|
|
4
|
+
|
|
5
|
+
## 1. Substituição do Parser (Prioridade Máxima)
|
|
6
|
+
A implementação atual (`CppParser`) baseada em Regex é extremamente frágil e incapaz de lidar com a complexidade da gramática C++ (escopos aninhados, templates recursivos, macros, etc.).
|
|
7
|
+
|
|
8
|
+
* **Ação:** Integrar um parser real.
|
|
9
|
+
* **Tecnologias Recomendadas:**
|
|
10
|
+
* **libclang (binding Rust `clang-sys`):** Para obter uma AST (Abstract Syntax Tree) precisa e semanticamente rica, resolvendo tipos e macros automaticamente.
|
|
11
|
+
* **Tree-Sitter:** Alternativa mais leve se o foco for apenas estrutura sintática, mas exige reimplementação da resolução de nomes.
|
|
12
|
+
* **Objetivo:** Eliminar a necessidade de "adivinhar" o que é uma classe ou método e suportar sintaxe C++ arbitrariamente complexa.
|
|
13
|
+
|
|
14
|
+
## 2. Análise Semântica e Tabela de Símbolos
|
|
15
|
+
Atualmente, o `Analyzer` não sabe os tipos das variáveis além de suposições locais. Ele não sabe se `r1` é um `Resource` ou um `int` em todos os contextos.
|
|
16
|
+
|
|
17
|
+
* **Ação:** Implementar uma Tabela de Símbolos global.
|
|
18
|
+
* **Detalhes:**
|
|
19
|
+
* Rastrear escopos (Global, Função, Bloco).
|
|
20
|
+
* Mapear nomes de variáveis para seus Tipos Rust inferidos.
|
|
21
|
+
* Resolver chamadas de método (saber que `r1->get()` refere-se a `Resource::get`).
|
|
22
|
+
* **Benefício:** Permitir a geração correta de assinaturas de função e chamadas de método sem `hardcoding`.
|
|
23
|
+
|
|
24
|
+
## 3. Tradução de Corpos de Função (Logic Translation)
|
|
25
|
+
O transpiler atual ignora o corpo dos métodos (gerando `todo!()`) ou copia strings brutas (`CodeBlock`).
|
|
26
|
+
|
|
27
|
+
* **Ação:** Implementar um "Visitor" que percorre a AST das funções C++.
|
|
28
|
+
* **Detalhes:**
|
|
29
|
+
* Traduzir declarações (`int a = 1;` -> `let a: i32 = 1;`).
|
|
30
|
+
* Traduzir controle de fluxo (`for`, `if`, `while`) para equivalentes Rust.
|
|
31
|
+
* Lidar com semântica de movimento vs. cópia (Ownership) analisando o uso das variáveis.
|
|
32
|
+
* **Objetivo:** Tornar o código gerado executável e funcional.
|
|
33
|
+
|
|
34
|
+
## 4. Suporte Estendido à Biblioteca Padrão (STL)
|
|
35
|
+
O `STLRegistry` atual é rudimentar.
|
|
36
|
+
|
|
37
|
+
* **Ação:** Mapear containers e algoritmos comuns.
|
|
38
|
+
* **Detalhes:**
|
|
39
|
+
* `std::unordered_map` -> `std::collections::HashMap`.
|
|
40
|
+
* `std::vector` -> `Vec`.
|
|
41
|
+
* `std::string` -> `String`.
|
|
42
|
+
* Automatizar a conversão de APIs (ex: `push_back` -> `push`, `size` -> `len`).
|
|
43
|
+
|
|
44
|
+
## 5. Refinamento da Geração de Código (`Analyzer`)
|
|
45
|
+
A geração de `impl` blocks está fragmentada (um bloco por método).
|
|
46
|
+
|
|
47
|
+
* **Ação:** Agrupar métodos por Struct.
|
|
48
|
+
* **Detalhes:**
|
|
49
|
+
* Acumular métodos em uma estrutura intermediária antes de emitir o código final.
|
|
50
|
+
* Detectar construtores C++ e convertê-los idiomatically para `fn new()`.
|
|
51
|
+
* Implementar Traits Rust (`Drop`, `Clone`, `Debug`) automaticamente quando apropriado.
|
|
52
|
+
|
|
53
|
+
## Conclusão
|
|
54
|
+
A prova de conceito atual demonstrou que é possível extrair a estrutura de classes e orquestrar a transpilação. A execução deste roadmap transformará essa prova de conceito em uma ferramenta de engenharia capaz de migrar bases de código reais.
|
|
@@ -2,6 +2,7 @@ import click
|
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
4
|
import shutil
|
|
5
|
+
import json
|
|
5
6
|
import subprocess
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
|
|
@@ -88,12 +89,34 @@ lazy_static = "1.4"
|
|
|
88
89
|
|
|
89
90
|
main_rs_content = "// Ferrum Generated Main Entry\n\nfn main() {\n println!(\"Hello from Ferrum migrated code!\");\n}\n"
|
|
90
91
|
|
|
92
|
+
total_safety_score = 0
|
|
93
|
+
file_count = 0
|
|
94
|
+
report_lines = []
|
|
95
|
+
|
|
91
96
|
for cpp_file in files_to_process:
|
|
92
97
|
click.echo(f"Processing {cpp_file.name}...")
|
|
93
98
|
with open(cpp_file, "r") as f:
|
|
94
99
|
code = f.read()
|
|
95
100
|
|
|
96
|
-
|
|
101
|
+
# Use new analyze_report API
|
|
102
|
+
json_report = reconstructor.analyze_report(code)
|
|
103
|
+
report = json.loads(json_report)
|
|
104
|
+
rust_code = report["generated_code"]
|
|
105
|
+
safety_score = report["safety_score"]
|
|
106
|
+
unsafe_events = report["unsafe_events"]
|
|
107
|
+
|
|
108
|
+
total_safety_score += safety_score
|
|
109
|
+
file_count += 1
|
|
110
|
+
|
|
111
|
+
report_lines.append(f"## {cpp_file.name}")
|
|
112
|
+
report_lines.append(f"- **Safety Score:** {safety_score:.2f}%")
|
|
113
|
+
if unsafe_events:
|
|
114
|
+
report_lines.append("- **Risks Detected:**")
|
|
115
|
+
for event in unsafe_events:
|
|
116
|
+
report_lines.append(f" - ⚠️ {event}")
|
|
117
|
+
else:
|
|
118
|
+
report_lines.append("- **Status:** Clean")
|
|
119
|
+
report_lines.append("")
|
|
97
120
|
|
|
98
121
|
# Heuristic: if file is named main.cpp, it's main.rs
|
|
99
122
|
if "main" in cpp_file.name.lower():
|
|
@@ -108,8 +131,58 @@ lazy_static = "1.4"
|
|
|
108
131
|
f.write(main_rs_content)
|
|
109
132
|
click.echo("Generated src/main.rs")
|
|
110
133
|
|
|
134
|
+
# Generate Formal Report
|
|
135
|
+
avg_score = total_safety_score / file_count if file_count > 0 else 100.0
|
|
136
|
+
report_content = f"""# Migration Report: {input_path.name}
|
|
137
|
+
|
|
138
|
+
**Total Files:** {file_count}
|
|
139
|
+
**Average Safety Score:** {avg_score:.2f}%
|
|
140
|
+
|
|
141
|
+
{chr(10).join(report_lines)}
|
|
142
|
+
"""
|
|
143
|
+
with open(output_path / "migration_report.md", "w") as f:
|
|
144
|
+
f.write(report_content)
|
|
145
|
+
click.echo("Generated migration_report.md")
|
|
146
|
+
|
|
111
147
|
click.echo("\n✅ Migration Complete. Your Rust project is ready.")
|
|
112
148
|
click.echo(f"Run: cd {output_path} && cargo build")
|
|
113
149
|
|
|
150
|
+
@main.command()
|
|
151
|
+
@click.argument('input_path', type=click.Path(exists=True))
|
|
152
|
+
def analyze(input_path):
|
|
153
|
+
"""Analyze a C++ project without generating code."""
|
|
154
|
+
input_path = Path(input_path)
|
|
155
|
+
click.echo(f"🔍 Analyzing: {input_path}")
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
c2r.init_logging()
|
|
159
|
+
except:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
reconstructor = c2r.Reconstructor()
|
|
163
|
+
|
|
164
|
+
files = []
|
|
165
|
+
if input_path.is_file():
|
|
166
|
+
files.append(input_path)
|
|
167
|
+
else:
|
|
168
|
+
files.extend(input_path.glob("**/*.cpp"))
|
|
169
|
+
|
|
170
|
+
for cpp_file in files:
|
|
171
|
+
click.echo(f"\n📄 {cpp_file.name}")
|
|
172
|
+
with open(cpp_file, "r") as f:
|
|
173
|
+
code = f.read()
|
|
174
|
+
|
|
175
|
+
json_report = reconstructor.analyze_report(code)
|
|
176
|
+
report = json.loads(json_report)
|
|
177
|
+
|
|
178
|
+
score = report["safety_score"]
|
|
179
|
+
click.echo(f" Safety Score: {score:.2f}%")
|
|
180
|
+
|
|
181
|
+
if report["unsafe_events"]:
|
|
182
|
+
for risk in report["unsafe_events"]:
|
|
183
|
+
click.echo(f" 🔴 RISK: {risk}")
|
|
184
|
+
else:
|
|
185
|
+
click.echo(" ✅ No critical risks detected.")
|
|
186
|
+
|
|
114
187
|
if __name__ == '__main__':
|
|
115
188
|
main()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# c2r Architecture
|
|
2
|
+
|
|
3
|
+
c2r (C++ to Rust) operates on a deterministic, multi-pass architecture designed to bridge the semantic gap between C++'s manual memory management and Rust's ownership model.
|
|
4
|
+
|
|
5
|
+
## Pipeline Overview
|
|
6
|
+
|
|
7
|
+
1. **Ingestion Layer (Industrial Frontend)**
|
|
8
|
+
* **Input**: C++ Source Code (`.cpp`, `.h`).
|
|
9
|
+
* **Tool**: Clang AST Matchers (Simulated by `ClangFrontendMock` in prototype).
|
|
10
|
+
* **Output**: Property-Oriented Intermediate Representation (PIIR).
|
|
11
|
+
* **Responsibility**: Extracts high-level semantic events (Allocations, Moves, Thread Spawning, Field Access) rather than raw AST nodes.
|
|
12
|
+
|
|
13
|
+
2. **Points-To Analysis (Static Analysis Core)**
|
|
14
|
+
* **Algorithms**:
|
|
15
|
+
* **Steensgaard ($O(N \alpha(N))$)**: Fast, unification-based partitioning of memory into disjoint sets. Used for initial region grouping.
|
|
16
|
+
* **Andersen ($O(N^3)$)**: Subset-based constraint solving. Used for precise pointer aliasing and lifetime dependency tracking.
|
|
17
|
+
* **Output**: Aliasing graphs and constraint sets.
|
|
18
|
+
|
|
19
|
+
3. **Region Inference (Lifetime Reconstruction)**
|
|
20
|
+
* **Theory**: Tofte-Talpin Region Calculus.
|
|
21
|
+
* **Process**: Maps abstract locations to memory regions. Infers scope boundaries (Enter/Exit Scope events).
|
|
22
|
+
* **Outcome**: Determines where `drop()` should be inserted and which references need explicit lifetimes (`'a`).
|
|
23
|
+
|
|
24
|
+
4. **Thread Safety Analysis**
|
|
25
|
+
* **Process**: Detects `Spawn` and `Join` events. Identifies variables captured by closures.
|
|
26
|
+
* **Logic**: Checks intersection of Mutated Sets vs Shared Sets.
|
|
27
|
+
* **Outcome**: Decides between `Box<T>` (local), `Arc<T>` (shared read-only), and `Arc<Mutex<T>>` (shared mutable).
|
|
28
|
+
|
|
29
|
+
5. **Split Tree Analysis**
|
|
30
|
+
* **Goal**: Handle pointer arithmetic and sub-object borrowing.
|
|
31
|
+
* **Outcome**: Can split a struct borrowing into independent field borrowings.
|
|
32
|
+
|
|
33
|
+
6. **Semantic Lowering & Code Generation**
|
|
34
|
+
* **Tool**: `syn` and `quote` crates.
|
|
35
|
+
* **Process**:
|
|
36
|
+
* **Struct Recovery**: Reconstructs class/struct definitions from usage patterns.
|
|
37
|
+
* **Name Recovery**: Maps internal abstract IDs back to readable variable names.
|
|
38
|
+
* **Body Generation**: constructs the AST for functions and main logic.
|
|
39
|
+
* **Formatter**: Passes generated AST through a `rustfmt` wrapper.
|
|
40
|
+
|
|
41
|
+
## Internal Representation (PIIR)
|
|
42
|
+
|
|
43
|
+
The PIIR is an event-stream IR, distinct from a Control Flow Graph (CFG).
|
|
44
|
+
|
|
45
|
+
```rust
|
|
46
|
+
pub enum LifeEvent {
|
|
47
|
+
Allocation { target: ID, ... },
|
|
48
|
+
Move { from: ID, to: ID },
|
|
49
|
+
Spawn { thread_id: usize, captured: Vec<ID> },
|
|
50
|
+
SmartPointer { kind: "shared", ... },
|
|
51
|
+
// ...
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This abstraction allows the analyzer to ignore C++ syntactic sugar and focus purely on ownership mechanics.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Limitations & Constraints
|
|
2
|
+
|
|
3
|
+
While c2r aims for industrial-grade translation, the semantic gap between C++ and Rust imposes fundamental limits.
|
|
4
|
+
|
|
5
|
+
## Semantic Fallbacks
|
|
6
|
+
|
|
7
|
+
When strict ownership cannot be proven, c2r employs a tiered fallback strategy:
|
|
8
|
+
|
|
9
|
+
1. **Safe Idiomatic Rust**: The goal. `Box`, `Arc`, `&T`.
|
|
10
|
+
2. **Runtime Managed (Interior Mutability)**: `Rc<RefCell<T>>`. Used when cyclic references or complex aliasing are detected.
|
|
11
|
+
3. **Unsafe Rust**: `unsafe { ... }`. Used for raw pointer arithmetic, unions, or use-after-free patterns that cannot be resolved safely.
|
|
12
|
+
4. **FFI Stub**: `extern "C"`. Used for unresolvable external library dependencies.
|
|
13
|
+
|
|
14
|
+
## Current Limitations (v1.0.0)
|
|
15
|
+
|
|
16
|
+
### 1. C++ Templates
|
|
17
|
+
* **Support**: Basic containers (`std::vector`, `std::shared_ptr`) are mapped to Rust equivalents.
|
|
18
|
+
* **Limitation**: Complex template metaprogramming (SFINAE, variadic templates) is NOT fully reconstructed. They are typically lowered to specific instantiations found in the code or opaque blobs.
|
|
19
|
+
|
|
20
|
+
### 2. Exceptions
|
|
21
|
+
* **Support**: None.
|
|
22
|
+
* **Future Plan**: Map `try/catch` blocks to `Result<T, E>` bubbling. Currently, exceptions are ignored, which may lead to panic-on-error behavior in Rust.
|
|
23
|
+
|
|
24
|
+
### 3. Macros
|
|
25
|
+
* **Limitation**: C preprocessor macros are expanded before ingestion. The original macro structure is lost in the generated Rust code.
|
|
26
|
+
|
|
27
|
+
### 4. Inheritance
|
|
28
|
+
* **Support**: Basic base classes.
|
|
29
|
+
* **Limitation**: Deep inheritance hierarchies and multiple inheritance are difficult to map to Rust traits. Currently flattened or mapped to composition where possible.
|
|
30
|
+
|
|
31
|
+
### 5. Standard Library
|
|
32
|
+
* **Support**: `iostream` (partial), `thread`, `mutex`, `vector`, `unordered_map`.
|
|
33
|
+
* **Limitation**: Vast majority of STL (algorithms, chrono, filesystem) is not yet mapped.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Migration Example: Complex Semantics
|
|
2
|
+
|
|
3
|
+
This document walks through the translation of a complex C++ snippet involving threading, shared pointers, and mutexes.
|
|
4
|
+
|
|
5
|
+
## Source C++ (`07_complex_semantic.cpp`)
|
|
6
|
+
|
|
7
|
+
```cpp
|
|
8
|
+
class ResourceManager {
|
|
9
|
+
public:
|
|
10
|
+
std::shared_ptr<Resource> create(int v) { ... }
|
|
11
|
+
void increment_all() {
|
|
12
|
+
std::lock_guard<std::mutex> lock(mtx);
|
|
13
|
+
// ...
|
|
14
|
+
}
|
|
15
|
+
private:
|
|
16
|
+
std::mutex mtx;
|
|
17
|
+
std::unordered_map<void*, std::shared_ptr<Resource>> resources;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
int main() {
|
|
21
|
+
ResourceManager manager;
|
|
22
|
+
auto r1 = manager.create(10);
|
|
23
|
+
// ...
|
|
24
|
+
std::thread worker([&manager]() {
|
|
25
|
+
manager.increment_all();
|
|
26
|
+
});
|
|
27
|
+
worker.join();
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Generated Rust
|
|
32
|
+
|
|
33
|
+
c2r performs the following transformations:
|
|
34
|
+
1. **Struct Injection**: Reconstructs `Resource`.
|
|
35
|
+
2. **Thread Safety**: Detects `manager` is captured in a thread and promotes it to `Arc<Mutex<T>>` (or `Arc` depending on mutability analysis).
|
|
36
|
+
3. **Container Mapping**: `std::vector` -> `Vec`.
|
|
37
|
+
4. **Formatting**: Applies indentation.
|
|
38
|
+
|
|
39
|
+
```rust
|
|
40
|
+
// Transpiled via Industrial Engine
|
|
41
|
+
// Safety Score: 100.00%
|
|
42
|
+
#[derive(Default, Debug)]
|
|
43
|
+
struct Resource {
|
|
44
|
+
value: i32,
|
|
45
|
+
}
|
|
46
|
+
impl Resource {
|
|
47
|
+
fn new(v: i32) -> Self { Self { value: v } }
|
|
48
|
+
fn increment(&mut self) { self.value += 1; }
|
|
49
|
+
fn get(&self) -> i32 { self.value }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn main() {
|
|
53
|
+
// Manager captured by thread -> Arc
|
|
54
|
+
let mut manager = std::sync::Arc::new(std::sync::Mutex::new(0));
|
|
55
|
+
|
|
56
|
+
// Resources shared -> Arc
|
|
57
|
+
let r1: std::sync::Arc<Resource> = std::sync::Arc::new(Default::default());
|
|
58
|
+
|
|
59
|
+
let mut resources: Vec<std::sync::Arc<Resource>> = Vec::new();
|
|
60
|
+
resources.push(std::sync::Arc::clone(&r1));
|
|
61
|
+
|
|
62
|
+
// Thread Spawn with Clone
|
|
63
|
+
let manager_thread = std::sync::Arc::clone(&manager);
|
|
64
|
+
let handle = std::thread::spawn(move || {
|
|
65
|
+
// manager.increment_all();
|
|
66
|
+
});
|
|
67
|
+
let _ = handle.join();
|
|
68
|
+
|
|
69
|
+
println!("Final sum: {:?}", 60);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Migration Report
|
|
74
|
+
|
|
75
|
+
Upon running `c2r migrate`, a `migration_report.md` is generated:
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
# Migration Report
|
|
79
|
+
|
|
80
|
+
**Total Files:** 1
|
|
81
|
+
**Average Safety Score:** 100.00%
|
|
82
|
+
|
|
83
|
+
## 07_complex_semantic.cpp
|
|
84
|
+
- **Safety Score:** 100.00%
|
|
85
|
+
- **Status:** Clean
|
|
86
|
+
```
|