Skip to content
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
22 changes: 20 additions & 2 deletions crates/bashkit/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2616,6 +2616,24 @@ impl Interpreter {
.await;
}

// Handle `let` - evaluate arithmetic expressions with assignment
if name == "let" {
let mut last_val = 0i64;
for arg in &args {
last_val = self.evaluate_arithmetic_with_assign(arg);
}
// let returns 1 if last expression is 0, 0 otherwise
let exit_code = if last_val == 0 { 1 } else { 0 };
let mut result = ExecResult {
stdout: String::new(),
stderr: String::new(),
exit_code,
control_flow: ControlFlow::None,
};
result = self.apply_redirections(result, &command.redirects).await?;
return Ok(result);
}

// Handle `unset` with array element syntax: unset 'arr[key]'
if name == "unset" {
for arg in &args {
Expand Down Expand Up @@ -3735,8 +3753,8 @@ impl Interpreter {
}
}
} else if is_integer {
// Try to evaluate as integer
let int_val: i64 = value.parse().unwrap_or(0);
// Evaluate as arithmetic expression
let int_val = self.evaluate_arithmetic_with_assign(value);
self.variables
.insert(var_name.to_string(), int_val.to_string());
} else {
Expand Down
88 changes: 88 additions & 0 deletions crates/bashkit/tests/spec_cases/bash/arithmetic.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -405,3 +405,91 @@ echo $((5 >= 3)); echo $((5 >= 5)); echo $((4 >= 5))
1
0
### end

### let_basic
# let evaluates arithmetic and assigns
let x=5+3
echo $x
### expect
8
### end

### let_multiple
# let evaluates multiple expressions
let a=2 b=3 c=a+b
echo $a $b $c
### expect
2 3 5
### end

### let_exit_zero
# let returns 0 when last expression is non-zero
let x=5
echo $?
### expect
0
### end

### let_exit_one
# let returns 1 when last expression is zero
let x=0
echo $?
### expect
1
### end

### let_increment
# let with increment operators
x=5; let x++
echo $x
### expect
6
### end

### let_compound_assign
# let with compound assignment
x=10; let x+=5
echo $x
### expect
15
### end

### let_no_args
# let with no arguments returns 1
let 2>/dev/null
echo $?
### expect
1
### end

### declare_i_basic
# declare -i evaluates arithmetic on assignment
declare -i x=5+3
echo $x
### expect
8
### end

### declare_i_expression
# declare -i with complex expression
declare -i x=2*3+4
echo $x
### expect
10
### end

### declare_i_variable_ref
# declare -i referencing other variables
a=5; b=3; declare -i x=a+b
echo $x
### expect
8
### end

### declare_i_plain_number
# declare -i with plain number
declare -i x=42
echo $x
### expect
42
### end
13 changes: 7 additions & 6 deletions specs/009-implementation-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,23 @@ Bashkit implements IEEE 1003.1-2024 Shell Command Language. See

## Spec Test Coverage

**Total spec test cases:** 1214 (1209 pass, 5 skip)
**Total spec test cases:** 1277 (1272 pass, 5 skip)

| Category | Cases | In CI | Pass | Skip | Notes |
|----------|-------|-------|------|------|-------|
| Bash (core) | 853 | Yes | 848 | 5 | `bash_spec_tests` in CI |
| Bash (core) | 859 | Yes | 854 | 5 | `bash_spec_tests` in CI |
| AWK | 96 | Yes | 96 | 0 | loops, arrays, -v, ternary, field assign, getline, %.6g |
| Grep | 76 | Yes | 76 | 0 | -z, -r, -a, -b, -H, -h, -f, -P, --include, --exclude, binary detect |
| Sed | 75 | Yes | 75 | 0 | hold space, change, regex ranges, -E |
| JQ | 114 | Yes | 114 | 0 | reduce, walk, regex funcs, --arg/--argjson, combined flags, input/inputs, env |
| **Total** | **1214** | **Yes** | **1209** | **5** | |
| Python | 57 | Yes | 57 | 0 | embedded Python (Monty) |
| **Total** | **1277** | **Yes** | **1272** | **5** | |

### Bash Spec Tests Breakdown

| File | Cases | Notes |
|------|-------|-------|
| arithmetic.test.sh | 57 | includes logical, bitwise, compound assign, increment/decrement |
| arithmetic.test.sh | 68 | includes logical, bitwise, compound assign, increment/decrement, `let` builtin, `declare -i` arithmetic |
| arrays.test.sh | 27 | indices, `${arr[@]}` / `${arr[*]}`, negative indexing `${arr[-1]}` |
| background.test.sh | 4 | |
| bash-command.test.sh | 34 | bash/sh re-invocation |
Expand Down Expand Up @@ -206,15 +207,15 @@ Features that may be added in the future (not intentionally excluded):

### Implemented

**92 core builtins + 3 feature-gated = 95 total**
**93 core builtins + 3 feature-gated = 96 total**

`echo`, `printf`, `cat`, `nl`, `cd`, `pwd`, `true`, `false`, `exit`, `test`, `[`,
`export`, `set`, `unset`, `local`, `source`, `.`, `read`, `shift`, `break`,
`continue`, `return`, `grep`, `sed`, `awk`, `jq`, `sleep`, `head`, `tail`,
`basename`, `dirname`, `mkdir`, `rm`, `cp`, `mv`, `touch`, `chmod`, `chown`, `ln`, `wc`,
`sort`, `uniq`, `cut`, `tr`, `paste`, `column`, `diff`, `comm`, `date`,
`wait`, `curl`, `wget`, `timeout`, `command`, `getopts`,
`type`, `which`, `hash`, `declare`, `typeset`, `kill`,
`type`, `which`, `hash`, `declare`, `typeset`, `let`, `kill`,
`time` (keyword), `whoami`, `hostname`, `uname`, `id`, `ls`, `rmdir`, `find`, `xargs`, `tee`,
`:` (colon), `eval`, `readonly`, `times`, `bash`, `sh`,
`od`, `xxd`, `hexdump`, `strings`,
Expand Down
Loading