Fixed disabling some pragmas and test to go with them
This commit is contained in:
parent
2d2d665ebd
commit
51b9476a85
9 changed files with 127 additions and 7 deletions
|
|
@ -173,7 +173,7 @@ func (c *GosubCommand) Generate(ctx *compiler.CompilerContext) ([]string, error)
|
|||
|
||||
// Check for immutable code pragma when using variable target
|
||||
if c.isVar {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" && c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "0" {
|
||||
return nil, fmt.Errorf("GOSUB: USE_IMMUTABLE_CODE pragma set but variable target requires self-modifying code")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ func (c *PeekCommand) Generate(ctx *compiler.CompilerContext) ([]string, error)
|
|||
|
||||
// Check for immutable code pragma when using self-modifying code
|
||||
if c.isAddrVar && !c.isZPPointer {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" && c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "0" {
|
||||
return nil, fmt.Errorf("PEEK: USE_IMMUTABLE_CODE pragma set but construct requires self-modifying code (consider using zero page word for address)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,3 +414,97 @@ func TestPeekWErrors(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeekImmutableCodePragma(t *testing.T) {
|
||||
// Test that _P_USE_IMMUTABLE_CODE pragma with value "1" causes error for variable address
|
||||
t.Run("Pragma enabled with 1", func(t *testing.T) {
|
||||
pragma := preproc.NewPragma()
|
||||
pragma.AddPragma("_P_USE_IMMUTABLE_CODE", "1")
|
||||
ctx := compiler.NewCompilerContext(pragma)
|
||||
|
||||
// Add a non-ZP word variable for address
|
||||
ctx.SymbolTable.AddVar("addr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
||||
ctx.SymbolTable.AddVar("result", "", compiler.KindByte, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
||||
|
||||
cmd := &PeekCommand{}
|
||||
line := preproc.Line{
|
||||
Text: "PEEK addr GIVING result",
|
||||
Kind: preproc.Source,
|
||||
PragmaSetIndex: pragma.GetCurrentPragmaSetIndex(),
|
||||
}
|
||||
|
||||
// First interpret the command
|
||||
err := cmd.Interpret(line, ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Interpret() error = %v", err)
|
||||
}
|
||||
|
||||
// Then generate code - this is where the pragma check happens
|
||||
_, err = cmd.Generate(ctx)
|
||||
if err == nil {
|
||||
t.Error("Expected error when _P_USE_IMMUTABLE_CODE=1 and using variable address, got nil")
|
||||
} else if !strings.Contains(err.Error(), "USE_IMMUTABLE_CODE pragma set") {
|
||||
t.Errorf("Expected error about USE_IMMUTABLE_CODE pragma, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Test that _P_USE_IMMUTABLE_CODE pragma with value "0" does NOT cause error
|
||||
t.Run("Pragma disabled with 0", func(t *testing.T) {
|
||||
pragma := preproc.NewPragma()
|
||||
pragma.AddPragma("_P_USE_IMMUTABLE_CODE", "0")
|
||||
ctx := compiler.NewCompilerContext(pragma)
|
||||
|
||||
// Add a non-ZP word variable for address
|
||||
ctx.SymbolTable.AddVar("addr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
||||
ctx.SymbolTable.AddVar("result", "", compiler.KindByte, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
||||
|
||||
cmd := &PeekCommand{}
|
||||
line := preproc.Line{
|
||||
Text: "PEEK addr GIVING result",
|
||||
Kind: preproc.Source,
|
||||
PragmaSetIndex: pragma.GetCurrentPragmaSetIndex(),
|
||||
}
|
||||
|
||||
// First interpret the command
|
||||
err := cmd.Interpret(line, ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Interpret() error = %v", err)
|
||||
}
|
||||
|
||||
// Then generate code - this is where the pragma check happens
|
||||
_, err = cmd.Generate(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when _P_USE_IMMUTABLE_CODE=0, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Test that _P_USE_IMMUTABLE_CODE pragma not set does NOT cause error
|
||||
t.Run("Pragma not set", func(t *testing.T) {
|
||||
pragma := preproc.NewPragma()
|
||||
// Don't add the pragma at all
|
||||
ctx := compiler.NewCompilerContext(pragma)
|
||||
|
||||
// Add a non-ZP word variable for address
|
||||
ctx.SymbolTable.AddVar("addr", "", compiler.KindWord, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
||||
ctx.SymbolTable.AddVar("result", "", compiler.KindByte, 0, preproc.Line{Filename: "test.c65", LineNo: 1})
|
||||
|
||||
cmd := &PeekCommand{}
|
||||
line := preproc.Line{
|
||||
Text: "PEEK addr GIVING result",
|
||||
Kind: preproc.Source,
|
||||
PragmaSetIndex: pragma.GetCurrentPragmaSetIndex(),
|
||||
}
|
||||
|
||||
// First interpret the command
|
||||
err := cmd.Interpret(line, ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Interpret() error = %v", err)
|
||||
}
|
||||
|
||||
// Then generate code - this is where the pragma check happens
|
||||
_, err = cmd.Generate(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when _P_USE_IMMUTABLE_CODE not set, got: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ func (c *PeekWCommand) Generate(ctx *compiler.CompilerContext) ([]string, error)
|
|||
// Case 3: Word variable (self-modifying code)
|
||||
if c.isAddrVar && c.addrVarKind == compiler.KindWord {
|
||||
// Check for immutable code pragma
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" && c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "0" {
|
||||
return nil, fmt.Errorf("PEEKW: USE_IMMUTABLE_CODE pragma set but construct requires self-modifying code (consider using zero page word for address)")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ func (c *PokeCommand) Generate(ctx *compiler.CompilerContext) ([]string, error)
|
|||
|
||||
// Check for immutable code pragma when using self-modifying code
|
||||
if c.isAddrVar && !c.isZPPointer {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" && c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "0" {
|
||||
return nil, fmt.Errorf("POKE: USE_IMMUTABLE_CODE pragma set but construct requires self-modifying code (consider using zero page word for address)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ func (c *PokeWCommand) Generate(ctx *compiler.CompilerContext) ([]string, error)
|
|||
|
||||
// Check for immutable code pragma when using self-modifying code
|
||||
if c.isAddrVar && c.addrVarKind == compiler.KindWord && !c.isZPPointer {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" {
|
||||
if c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "" && c.pragmaSet.GetPragma("_P_USE_IMMUTABLE_CODE") != "0" {
|
||||
return nil, fmt.Errorf("POKEW: USE_IMMUTABLE_CODE pragma set but construct requires self-modifying code (consider using zero page word for address)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func NewConstantStringHandler() *ConstantStringHandler {
|
|||
}
|
||||
|
||||
func (h *ConstantStringHandler) AddConstStr(label, value string, compress bool, ps preproc.PragmaSet) string {
|
||||
useCBM := ps.GetPragma("_P_USE_CBM_STRINGS") != ""
|
||||
useCBM := ps.GetPragma("_P_USE_CBM_STRINGS") != "" && ps.GetPragma("_P_USE_CBM_STRINGS") != "0"
|
||||
|
||||
if compress {
|
||||
if existingLabel, exists := h.compressMap[value]; exists {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,31 @@ func TestGenerateConstStrDecls_CBM(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGenerateConstStrDecls_CBM_DisabledWithZero(t *testing.T) {
|
||||
h := NewConstantStringHandler()
|
||||
ps := mockPragmaSet(map[string]string{"_P_USE_CBM_STRINGS": "0"})
|
||||
|
||||
h.AddConstStr("str1", "\"hello\"", false, ps)
|
||||
|
||||
result := h.GenerateConstStrDecls()
|
||||
|
||||
expected := []string{
|
||||
"str1",
|
||||
" !raw \"hello\"",
|
||||
" !8 0",
|
||||
}
|
||||
|
||||
if len(result) != len(expected) {
|
||||
t.Fatalf("Expected %d lines, got %d", len(expected), len(result))
|
||||
}
|
||||
|
||||
for i, exp := range expected {
|
||||
if result[i] != exp {
|
||||
t.Errorf("Line %d: expected %q, got %q", i, exp, result[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateConstStrDecls_MixedPragmas(t *testing.T) {
|
||||
h := NewConstantStringHandler()
|
||||
psNormal := preproc.PragmaSet{}
|
||||
|
|
|
|||
|
|
@ -241,11 +241,12 @@ Sets compiler pragmas (options).
|
|||
- Prevents self-modifying code generation
|
||||
- Required for ROM-based code
|
||||
- Errors on PEEK/POKE/GOSUB with variable addresses
|
||||
- Value: any non-zero value enables
|
||||
|
||||
**_P_USE_CBM_STRINGS**
|
||||
- Encodes strings in CBM PETSCII format
|
||||
- Default: ASCII encoding
|
||||
- Value: any non-empty value enables
|
||||
- Value: any non-zero value enables
|
||||
|
||||
**_P_IGNORE_UNUSED**
|
||||
- Suppresses "variable declared but never used" warnings
|
||||
|
|
|
|||
Loading…
Reference in a new issue