131 lines
3.3 KiB
Go
131 lines
3.3 KiB
Go
package commands
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"c65gm/internal/compiler"
|
|
"c65gm/internal/preproc"
|
|
)
|
|
|
|
func TestPointerCommand_Generate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
line string
|
|
setupVars func(*compiler.SymbolTable)
|
|
wantAsm []string
|
|
}{
|
|
{
|
|
name: "pointer to label — uses A only",
|
|
line: "POINTER ptr -> TARGET",
|
|
setupVars: func(st *compiler.SymbolTable) {
|
|
st.AddVar("ptr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
|
},
|
|
wantAsm: []string{
|
|
"\tlda #<TARGET",
|
|
"\tsta ptr",
|
|
"\tlda #>TARGET",
|
|
"\tsta ptr+1",
|
|
},
|
|
},
|
|
{
|
|
name: "pointer to variable — uses A only",
|
|
line: "POINTER ptr TO targetVar",
|
|
setupVars: func(st *compiler.SymbolTable) {
|
|
st.AddVar("ptr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
|
st.AddVar("targetVar", "", compiler.KindByte, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
|
},
|
|
wantAsm: []string{
|
|
"\tlda #<targetVar",
|
|
"\tsta ptr",
|
|
"\tlda #>targetVar",
|
|
"\tsta ptr+1",
|
|
},
|
|
},
|
|
{
|
|
name: "pointer to numeric address — uses A only",
|
|
line: "POINTER ptr -> 53280",
|
|
setupVars: func(st *compiler.SymbolTable) {
|
|
st.AddVar("ptr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
pragma := preproc.NewPragma()
|
|
ctx := compiler.NewCompilerContext(pragma)
|
|
tt.setupVars(ctx.SymbolTable)
|
|
|
|
cmd := &PointerCommand{}
|
|
line := preproc.Line{
|
|
Text: tt.line,
|
|
Kind: preproc.Source,
|
|
PragmaSetIndex: pragma.GetCurrentPragmaSetIndex(),
|
|
}
|
|
|
|
if err := cmd.Interpret(line, ctx); err != nil {
|
|
t.Fatalf("Interpret() error = %v", err)
|
|
}
|
|
|
|
asm, err := cmd.Generate(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Generate() error = %v", err)
|
|
}
|
|
|
|
if tt.name == "pointer to numeric address — uses A only" {
|
|
foundLo := false
|
|
foundHi := false
|
|
foundSta := false
|
|
for _, a := range asm {
|
|
if strings.Contains(a, "lda #<") {
|
|
foundLo = true
|
|
}
|
|
if strings.Contains(a, "lda #>") {
|
|
foundHi = true
|
|
}
|
|
if strings.Contains(a, "sta ptr+1") {
|
|
foundSta = true
|
|
}
|
|
}
|
|
if !foundLo || !foundHi || !foundSta {
|
|
t.Errorf("expected A-only pattern (lda #< / sta ptr / lda #> / sta ptr+1), got:\n%s", strings.Join(asm, "\n"))
|
|
}
|
|
return
|
|
}
|
|
|
|
if !equalAsm(asm, tt.wantAsm) {
|
|
t.Errorf("Generate() mismatch\ngot:\n%s\nwant:\n%s",
|
|
strings.Join(asm, "\n"),
|
|
strings.Join(tt.wantAsm, "\n"))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPointerCommand_NoXRegister(t *testing.T) {
|
|
pragma := preproc.NewPragma()
|
|
ctx := compiler.NewCompilerContext(pragma)
|
|
ctx.SymbolTable.AddVar("ptr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
|
|
|
cmd := &PointerCommand{}
|
|
line := preproc.Line{
|
|
Text: "POINTER ptr -> $0400",
|
|
Kind: preproc.Source,
|
|
PragmaSetIndex: pragma.GetCurrentPragmaSetIndex(),
|
|
}
|
|
|
|
if err := cmd.Interpret(line, ctx); err != nil {
|
|
t.Fatalf("Interpret() error = %v", err)
|
|
}
|
|
|
|
asm, err := cmd.Generate(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Generate() error = %v", err)
|
|
}
|
|
|
|
joined := strings.Join(asm, "\n")
|
|
if strings.Contains(joined, "ldx") || strings.Contains(joined, "stx") {
|
|
t.Errorf("POINTER should not use X register, got:\n%s", joined)
|
|
}
|
|
}
|