amber-lang / amber-lang/bash2amber
[Detail Bug] Bash→Amber conversion drops redirections on compound commands (if/while/for/group)
- 主要言語
- Rust
- スター
- 2
- フォーク
- 0
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
# Summary
- **Context**: `src/bash/ast.rs` defines the Abstract Syntax Tree for Bash commands, which are later converted into Amber code.
- **Bug**: Compound commands (such as `if`, `while`, `for`, `case`, and `{...}` groups) do not have a field to store redirections.
- **Actual vs. expected**: When a compound command is followed by a redirection (e.g., `if ... fi > file.txt`), the parser treats the redirection as a separate `SimpleCommand` instead of attaching it to the compound command.
- **Impact**: Redirections on compound commands are silently lost or applied incorrectly to an empty command, leading to broken logic in the generated Amber code.
# Code with bug
```rust
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IfCommand {
pub condition: Box,
pub then_body: Vec,
pub else_body: Option>,
// <-- BUG 🔴 Missing redirects field
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WhileCommand {
pub condition: Box,
pub body: Vec,
// <-- BUG 🔴 Missing redirects field
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ForCommand {
pub variable: String,
pub items: Vec,
pub body: Vec,
// <-- BUG 🔴 Missing redirects field
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Command {
// ...
Group(Vec), // <-- BUG 🔴 This should probably be a struct with a redirects field
}
```
# Evidence
### Reproduction Script (`repro_bug.sh`)
```bash
if true; then echo "hi"; fi > log.txt
```
### Actual Conversion Output
```amber
if trust $ true $ {
echo("hi")
}
trust $ > log.txt $
```
The output shows that the `if` statement and the redirection `> log.txt` have been split into two separate statements. In the original Bash script, "hi" should be written to `log.txt`. In the converted Amber code, "hi" is printed to the standard output, and an empty `log.txt` is created.
### Group Redirection Reproduction (`repro_group.sh`)
```bash
{ echo "a"; echo "b"; } > log.txt
```
### Actual Conversion Output
```amber
echo("a")
echo("b")
trust $ > log.txt $
```
Again, the redirection is separated from the block it was supposed to redirect.
# Why has this bug gone undetected?
The conversion process uses a "trust fallback" mechanism for many Bash features. For `SimpleCommand`s like `echo hi > log.txt`, the redirection is kept as part of the `words` list and rendered inside a `trust $ ... $` block, which happens to work because the shell then interprets it correctly. However, for compound commands, the parser is designed to recognize keywords like `if` and `fi`, and it stops parsing the compound command as soon as it sees the closing keyword. Since the AST has no place to store what follows, the redirection is left for the next iteration of the parser loop, which treats it as a new (and separate) command.
# Recommended fix
1. Update the structs in `src/bash/ast.rs` to include a `redirects` field (e.g., `pub redirects: Vec` or a more structured `Redirect` enum).
2. Update `src/bash/parser.rs` to parse redirections after compound command keywords (like `fi`, `done`, `esac`, `}`) and attach them to the command node.
3. Update the rendering logic in `src/amber/render/` to wrap compound commands with redirections in a `trust $ ... $` block if they cannot be represented natively in Amber.
# History
This bug was introduced in commit 3abfff4 (@Ph0enixKM, 2026-02-07). The initial implementation of the Bash AST and parser defined compound commands (if, while, for, etc.) as fixed structures that terminate immediately after their closing keywords, failing to account for trailing I/O redirections which are then incorrectly parsed as separate simple commands.
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
評価
この issue はまだ評価されていません。