You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 line
6.0KB

  1. # E03-S01: run the parser over every fixture in x128 and check the ERR files
  2. # and the recorded top-level types against the fixtures' expectations.
  3. [CmdletBinding()]
  4. param([int]$Port = 6535, [int]$TimeoutSeconds = 300)
  5. $ErrorActionPreference = "Stop"
  6. $project = Split-Path $PSScriptRoot -Parent
  7. Import-Module (Join-Path $PSScriptRoot "lib\Nova128Test.psm1") -Force
  8. . (Join-Path $PSScriptRoot "build-parser-test.ps1") # defines $ParserFixtures
  9. $out = Join-Path $project "build\parser-test"
  10. $disk = Join-Path $out "parser-test.d81"
  11. # Catalog: symbol -> number.
  12. $codes = @{}
  13. foreach ($line in Get-Content (Join-Path $project "src\common\diagcat.inc")) {
  14. $m = [regex]::Match($line, '^\s*DIAGNOSTIC\s+(\w+),\s*(\d+),')
  15. if ($m.Success) { $codes[$m.Groups[1].Value] = [int]$m.Groups[2].Value }
  16. }
  17. $session = Start-Nova128X128 -Autostart $disk -Drive8Image $disk -Port $Port `
  18. -Screenshot (Join-Path $out "parser-test-vicii.png")
  19. try {
  20. $mb = Wait-Nova128Mailbox $session -TimeoutSeconds $TimeoutSeconds
  21. $dump = Read-Nova128Memory $session ($mb[8] + 256 * $mb[9]) ($mb[10] + 256 * $mb[11])
  22. } finally {
  23. Stop-Nova128X128 $session
  24. }
  25. if ($mb[3] -ne 0xA5) { throw ("C128 reported FAIL (code `${0:X2})" -f $mb[4]) }
  26. # ------------------------------------------------------------ decode dump
  27. $records = @(); $p = 0
  28. while ($dump[$p] -ne 0xFE) {
  29. if ($dump[$p] -ne 0xFF) { throw "dump out of sync at $p" }
  30. $r = [pscustomobject]@{ Index = $dump[$p + 1]; Load = $dump[$p + 2]; Count = $dump[$p + 3]; Types = @() }
  31. $p += 4
  32. while ($dump[$p] -ne 0xFD) {
  33. $len = $dump[$p + 3]
  34. $spell = -join ($dump[($p + 4)..($p + 3 + $len)] | ForEach-Object {
  35. if ($_ -ge 0x41 -and $_ -le 0x5A) { [char]($_ + 0x20) } elseif ($_ -ge 0xC1 -and $_ -le 0xDA) { [char]($_ - 0x80) } else { [char]$_ } })
  36. $r.Types += ("{0} {1} {2}" -f @("", "interface", "class", "program")[$dump[$p]], $spell, ($dump[$p + 1] + 256 * $dump[$p + 2]))
  37. $p += 4 + $len
  38. }
  39. $p++
  40. $records += $r
  41. }
  42. $c1541 = Get-ViceTool "c1541"
  43. $listing = (& $c1541 -attach $disk -list 2>&1) | Out-String
  44. function Get-ErrLines([string]$base) {
  45. $dest = Join-Path $out "$base.err.bin"
  46. if (Test-Path $dest) { Remove-Item $dest -Force }
  47. if ($listing -notmatch ('"' + [regex]::Escape("$base.err") + '"')) { return $null }
  48. & $c1541 -attach $disk -read "$base.err,s" $dest 2>&1 | Out-Null
  49. # The leading comma keeps a one-line file an array (PowerShell unrolls it).
  50. return ,@(([Text.Encoding]::ASCII.GetString([IO.File]::ReadAllBytes($dest)).TrimEnd("`r")) -split "`r")
  51. }
  52. function Parse-Err([string]$line) {
  53. $m = [regex]::Match($line, '^E(\d{3}) \S+ (\d+) (\d+) ')
  54. return [pscustomobject]@{ Code = [int]$m.Groups[1].Value; Line = [int]$m.Groups[2].Value; Col = [int]$m.Groups[3].Value }
  55. }
  56. # ---------------------------------------------------------------- check
  57. $failures = @(); $i = 0; $pending = @()
  58. foreach ($name in $ParserFixtures.Keys) {
  59. $src, $group, $expect = $ParserFixtures[$name]
  60. $base = $name -replace '\.n8$', ''
  61. $r = $records[$i]; $i++
  62. $errLines = Get-ErrLines $base
  63. $problems = @()
  64. if ($r.Load -ne 0) { $problems += "src_load returned $($r.Load)" }
  65. switch ($group) {
  66. "accepted" {
  67. if ($r.Count -ne 0) { $problems += "$($r.Count) diagnostic(s): $($errLines -join ' | ')" }
  68. if ($null -ne $errLines) { $problems += "an ERR file exists" }
  69. $want = @()
  70. $n = 0
  71. foreach ($line in Get-Content -LiteralPath $src) {
  72. $n++
  73. $m = [regex]::Match($line, '^\s*(interface|class|program)\s+(\w+)')
  74. if ($m.Success) { $want += ("{0} {1} {2}" -f $m.Groups[1].Value, $m.Groups[2].Value, $n) }
  75. }
  76. if ((($r.Types | Sort-Object) -join ';') -ne (($want | Sort-Object) -join ';')) {
  77. $problems += "types [$($r.Types -join '; ')] expected [$($want -join '; ')]"
  78. }
  79. $detail = "{0} types" -f $r.Types.Count
  80. }
  81. "rejected" {
  82. $text = Get-Content -Raw -LiteralPath $expect
  83. $sym = [regex]::Match($text, '(?m)^diagnostic: (\w+)').Groups[1].Value
  84. $wantLine = [int][regex]::Match($text, '(?m)^line: (\d+)').Groups[1].Value
  85. $colMatch = [regex]::Match($text, '(?m)^column: (\d+)')
  86. if ($null -eq $errLines) { $problems += "no ERR file" }
  87. else {
  88. $first = Parse-Err $errLines[0]
  89. if ($first.Code -ne $codes[$sym] -or $first.Line -ne $wantLine -or
  90. ($colMatch.Success -and $first.Col -ne [int]$colMatch.Groups[1].Value)) {
  91. $problems += "first diagnostic '$($errLines[0])' expected $sym (E$($codes[$sym])) at line $wantLine"
  92. }
  93. }
  94. $detail = if ($errLines) { $errLines[0] } else { "" }
  95. }
  96. "pending" {
  97. if ($r.Count -ne 0) { $problems += "false diagnostic(s) before E03-S03: $($errLines -join ' | ')" }
  98. $pending += $name
  99. $detail = "pending E03-S03 (statement grammar); no false errors"
  100. }
  101. "exact" {
  102. $want = @(Get-Content -LiteralPath $expect | Where-Object { $_ -and -not $_.StartsWith("//") } | ForEach-Object {
  103. $f = $_ -split ' '; "{0} {1} {2}" -f $codes[$f[0]], $f[1], $f[2] })
  104. $got = @($errLines | Where-Object { $_ } | ForEach-Object { $e = Parse-Err $_; "{0} {1} {2}" -f $e.Code, $e.Line, $e.Col })
  105. if (($got -join ';') -ne ($want -join ';')) {
  106. $problems += "diagnostics [$($got -join '; ')] expected [$($want -join '; ')]"
  107. }
  108. $detail = "{0} diagnostics" -f $got.Count
  109. }
  110. }
  111. $status = if ($problems) { "FAIL" } else { "ok" }
  112. Write-Host (" {0,-13} {1,-9} {2} {3}" -f $name, $group, $status, $detail)
  113. if ($problems) { $failures += "${name}: " + ($problems -join "; ") }
  114. }
  115. if ($failures) { throw ("parser verification failed:`n " + ($failures -join "`n ")) }
  116. Write-Host ("verified parser: {0} fixtures ({1} pending E03-S03)" -f $ParserFixtures.Count, $pending.Count)

Powered by TurnKey Linux.