c65gm/internal/compiler/command.go

59 lines
1.7 KiB
Go

package compiler
import (
"fmt"
"c65gm/internal/preproc"
)
// Command represents a script command that can interpret source lines and generate assembly
type Command interface {
// WillHandle checks if this command can handle the given line
// Should clear any internal state and return true if it handles this line
WillHandle(line preproc.Line) bool
// Interpret parses and validates the line, storing state in the command
// Returns error if line is malformed or invalid
Interpret(line preproc.Line, ctx *CompilerContext) error
// Generate produces assembly output based on previously interpreted line
// Returns assembly lines and error if generation fails
Generate(ctx *CompilerContext) ([]string, error)
}
// CommandRegistry manages registered commands and dispatches lines to appropriate handlers
type CommandRegistry struct {
commands []Command
}
// NewCommandRegistry creates a new command registry
func NewCommandRegistry() *CommandRegistry {
return &CommandRegistry{
commands: make([]Command, 0),
}
}
// Register adds a command to the registry
func (r *CommandRegistry) Register(cmd Command) {
r.commands = append(r.commands, cmd)
}
// FindHandler finds the first command that will handle the given line
// Returns the command and true if found, nil and false otherwise
func (r *CommandRegistry) FindHandler(line preproc.Line) (Command, bool) {
for _, cmd := range r.commands {
if cmd.WillHandle(line) {
return cmd, true
}
}
return nil, false
}
// UnhandledLineError represents an error when no command handles a source line
type UnhandledLineError struct {
Line preproc.Line
}
func (e *UnhandledLineError) Error() string {
return fmt.Sprintf("%s:%d: unhandled line: %s", e.Line.Filename, e.Line.LineNo, e.Line.Text)
}