c65gm/internal/commands/switch.go

82 lines
2 KiB
Go

package commands
import (
"fmt"
"strings"
"c65gm/internal/compiler"
"c65gm/internal/preproc"
"c65gm/internal/utils"
)
// SwitchCommand handles SWITCH statements
// Syntax: SWITCH <variable>
type SwitchCommand struct {
}
func (c *SwitchCommand) WillHandle(line preproc.Line) bool {
params, err := utils.ParseParams(line.Text)
if err != nil || len(params) == 0 {
return false
}
return strings.ToUpper(params[0]) == "SWITCH"
}
func (c *SwitchCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext) error {
params, err := utils.ParseParams(line.Text)
if err != nil {
return err
}
if len(params) != 2 {
return fmt.Errorf("SWITCH: expected 2 parameters (SWITCH <variable>), got %d", len(params))
}
scope := ctx.CurrentScope()
constLookup := func(name string) (int64, bool) {
sym := ctx.SymbolTable.Lookup(name, scope)
if sym != nil && sym.IsConst() {
return int64(sym.Value), true
}
return 0, false
}
// Parse the switch variable/expression
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
params[1], ctx.SymbolTable, scope, constLookup)
if err != nil {
return fmt.Errorf("SWITCH: %w", err)
}
// Check pragma for long jumps
ps := ctx.Pragma.GetPragmaSetByIndex(line.PragmaSetIndex)
longJumpPragma := ps.GetPragma("_P_USE_LONG_JUMP")
useLongJump := longJumpPragma != "" && longJumpPragma != "0"
// Create end label
endLabel := ctx.GeneralStack.Push()
// Create and push switch info
switchInfo := &compiler.SwitchInfo{
SwitchOperand: &compiler.OperandInfo{
VarName: varName,
VarKind: varKind,
Value: value,
IsVar: isVar,
},
EndLabel: endLabel,
NeedsPendingCode: false,
PendingSkipLabel: "",
HasDefault: false,
UseLongJump: useLongJump,
}
ctx.SwitchStack.Push(switchInfo)
return nil
}
func (c *SwitchCommand) Generate(ctx *compiler.CompilerContext) ([]string, error) {
// SWITCH itself generates no assembly code
// The variable will be loaded and compared by each CASE
return []string{}, nil
}