Skip to content

Improve error handling #143

Improve error handling

Improve error handling #143

Workflow file for this run

name: Rust
on:
push:
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
linux-ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fetch
run: cargo fetch
- name: Build
run: cargo build --release --verbose
- name: Run tests
run: cargo test --release --verbose
- name: Run fmt check
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --release --all-targets -- -D warnings
# The examples are the only programs compiled and run end to end through
# the real driver -- shelling out to the assembler and linker -- rather
# than through the test harness.
- name: Compile and run the examples
shell: bash
run: |
set -euo pipefail
for f in examples/*.bas; do
echo "== $f"
./target/release/xbasic64 "$f" -o /tmp/example
/tmp/example </dev/null >/dev/null
done
windows-native:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install LLVM/Clang
run: choco install llvm -y
- name: Add LLVM to PATH
run: echo "C:\Program Files\LLVM\bin" >> $env:GITHUB_PATH
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Build
run: cargo build --release --verbose
- name: Run tests
run: cargo test --release --verbose
- name: Run fmt check
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --release --all-targets -- -D warnings
# Worth repeating here rather than trusting the Linux job: this is the
# only step that drives link.exe over whole programs, and the Win64
# runtime is the half that cannot be run anywhere else.
#
# Deliberately PowerShell, the shell the rest of this job uses. Under
# `shell: bash` the PATH leads with Git for Windows' usr/bin, whose GNU
# coreutils `link.exe` shadows the MSVC linker -- the compiler then hands
# MSVC flags to coreutils and gets "extra operand '/SUBSYSTEM:CONSOLE'".
- name: Compile and run the examples
shell: pwsh
run: |
Get-ChildItem examples/*.bas | ForEach-Object {
Write-Host "== $($_.Name)"
& ./target/release/xbasic64.exe $_.FullName -o example.exe
if ($LASTEXITCODE -ne 0) { throw "compile failed: $($_.Name)" }
& ./example.exe | Out-Null
# Report the code, not just the failure. Windows says what went
# wrong in it, and nothing else here can: 1 is the compiler's own
# diagnosed abort, while 0xC0000005 (access violation), 0xC0000409
# (stack buffer overrun) and 0xC0000374 (heap corruption) each name
# a different defect, and none of the three can be reproduced on
# the Linux job.
if ($LASTEXITCODE -ne 0) {
# `-f` with X8 renders a negative Int32 as its two's-complement
# hex on its own. Masking first needed no cast and got one: in
# PowerShell 0xFFFFFFFF is Int32 -1, so the -band was a no-op and
# [uint32] then threw on the very value it was there to show.
throw ("run failed: {0} (exit {1}, 0x{2:X8})" -f $_.Name, $LASTEXITCODE, $LASTEXITCODE)
}
}
# An example is a whole program, so a crash in one names the program and
# not the statement. These are one statement each, and they are the only
# coverage the console statements have anywhere: the test suite runs on
# Linux, and CLS, LOCATE and COLOR are precisely the helpers whose two
# implementations differ most.
#
# Every probe runs, and the step reports the whole table before failing,
# so one CI run says which statements are broken rather than the first.
- name: Probe each console statement
if: always()
shell: pwsh
run: |
$probes = [ordered]@{
'CLS' = 'CLS'
'CLS after PRINT' = "PRINT `"x`"`nCLS"
'CLS twice' = "CLS`nCLS"
'PRINT alone' = 'PRINT "x"'
'COLOR' = 'COLOR 14, 1'
'LOCATE' = 'LOCATE 2, 5'
'LOCATE row only' = 'LOCATE 3'
'POS' = 'PRINT POS(0)'
'TIMER' = 'PRINT TIMER'
'RANDOMIZE n' = 'RANDOMIZE 42'
'RANDOMIZE TIMER' = 'RANDOMIZE TIMER'
'RND' = 'PRINT RND'
'RND(0)' = 'PRINT RND(0)'
'BEEP' = 'BEEP'
'DATE$' = 'PRINT DATE$'
'TIME$' = 'PRINT TIME$'
'FRE' = 'PRINT FRE(0)'
'DEFINT' = "DEFINT A-Z`nX = 3`nPRINT X"
'EQV' = 'PRINT 1 EQV 1'
'ERASE' = "DIM A(3)`nERASE A"
'SYSTEM' = 'SYSTEM'
}
$failed = @()
foreach ($p in $probes.GetEnumerator()) {
Set-Content -Path probe.bas -Value $p.Value
& ./target/release/xbasic64.exe probe.bas -o probe.exe | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host ("{0,-20} DID NOT COMPILE" -f $p.Key)
$failed += $p.Key
continue
}
& ./probe.exe | Out-Null
$code = $LASTEXITCODE
Write-Host ("{0,-20} exit {1} (0x{2:X8})" -f $p.Key, $code, $code)
if ($code -ne 0) { $failed += $p.Key }
}
if ($failed.Count -gt 0) { throw "crashed: $($failed -join ', ')" }