feat: gasm-devkit 0.1.0 — GAsm lexer, parser, linter, formatter, LSP and amd64 assembler
Assisted-by: Qwen 3.8 Max Preview
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package lint
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"sourcedock.dev/petrbalvin/gasm-devkit/arch"
|
||||
"sourcedock.dev/petrbalvin/gasm-devkit/parser"
|
||||
)
|
||||
|
||||
// TestGoRuntimeCorpus parses and lints every runtime .s file the local Go
|
||||
// toolchain ships for all four supported architectures. This is the
|
||||
// real-world regression net: it exercises the full breadth of each
|
||||
// architecture's syntax (macros, addressing modes, branch aliases) against
|
||||
// production assembly. It is skipped when the toolchain source is absent.
|
||||
//
|
||||
// The bar is zero parse errors and zero error-severity diagnostics — i.e. no
|
||||
// false "unknown instruction" / "undefined label" findings on code the real
|
||||
// assembler accepts. Advisory warnings are reported but not fatal, since they
|
||||
// are heuristics that may legitimately differ across Go versions.
|
||||
func TestGoRuntimeCorpus(t *testing.T) {
|
||||
dir := filepath.Join(runtime.GOROOT(), "src", "runtime")
|
||||
var files []string
|
||||
for _, suffix := range []string{"_amd64.s", "_arm64.s", "_riscv64.s", "_loong64.s"} {
|
||||
matches, _ := filepath.Glob(filepath.Join(dir, "*"+suffix))
|
||||
files = append(files, matches...)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
t.Skip("Go toolchain source (src/runtime/*.s) not present")
|
||||
}
|
||||
|
||||
warnings := 0
|
||||
for _, path := range files {
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("read %s: %v", path, err)
|
||||
}
|
||||
f, errs := parser.Parse(path, string(src))
|
||||
if len(errs) > 0 {
|
||||
t.Errorf("parse %s: %v", filepath.Base(path), errs)
|
||||
continue
|
||||
}
|
||||
diags := File(f, Config{Arch: arch.FromFilename(path)})
|
||||
for _, d := range diags {
|
||||
if d.Severity == Error {
|
||||
t.Errorf("%s:%d: error %s: %s", filepath.Base(path), d.Pos.Line, d.Code, d.Message)
|
||||
} else {
|
||||
warnings++
|
||||
}
|
||||
}
|
||||
}
|
||||
if warnings > 0 {
|
||||
t.Logf("%d advisory warnings across %d files (non-fatal)", warnings, len(files))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user