c65gm/main.go

118 lines
3.7 KiB
Go

package main
import (
"flag"
"fmt"
"os"
"strings"
"c65gm/internal/commands"
"c65gm/internal/compiler"
"c65gm/internal/preproc"
)
// c65gm - A 6502 Cross-Compiler for the ACME Cross-Assembler
// Copyright (C) 1999, 2025 Mattias Hansson
// Distributed under GPL.
func main() {
fmt.Println("c65gm - A 6502 Cross-Compiler for the ACME Cross-Assembler.")
fmt.Println("Copyright (C) 1999, 2025 Mattias Hansson. v1.0.0")
fmt.Println("Distributed under GPL.")
fmt.Println()
inFile := flag.String("in", "", "input source file (required)")
outFile := flag.String("out", "", "output assembly file (required)")
flag.Parse()
if *inFile == "" || *outFile == "" {
_, _ = fmt.Fprintln(os.Stderr, "Error: -in and -out are required")
flag.Usage()
os.Exit(1)
}
if err := run(*inFile, *outFile); err != nil {
if _, ok := err.(preproc.HaltError); ok {
fmt.Println("Halted by #HALT directive")
os.Exit(2)
}
_, _ = fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
fmt.Println("Compilation successful.")
}
func run(inFile, outFile string) error {
// Preprocess
lines, pragma, err := preproc.PreProcess(inFile)
if err != nil {
return fmt.Errorf("preprocessing failed: %w", err)
}
fmt.Printf("Preprocessed %d lines\n", len(lines))
// Create compiler and register commands
comp := compiler.NewCompiler(pragma)
registerCommands(comp)
// Compile
asmLines, err := comp.Compile(lines)
if err != nil {
return fmt.Errorf("compilation failed: %w", err)
}
fmt.Printf("Generated %d lines of assembly\n", len(asmLines))
// Write output
if err := writeOutput(outFile, asmLines); err != nil {
return fmt.Errorf("failed to write output: %w", err)
}
return nil
}
func registerCommands(comp *compiler.Compiler) {
// Register all command handlers here
// This is the single place where all commands are wired up
comp.Registry().Register(&commands.ByteCommand{})
comp.Registry().Register(&commands.WordCommand{})
comp.Registry().Register(&commands.AddCommand{})
comp.Registry().Register(&commands.AndCommand{})
comp.Registry().Register(&commands.OrCommand{})
comp.Registry().Register(&commands.XorCommand{})
comp.Registry().Register(&commands.SubtractCommand{})
comp.Registry().Register(&commands.LetCommand{})
comp.Registry().Register(&commands.IfCommand{})
comp.Registry().Register(&commands.ElseCommand{})
comp.Registry().Register(&commands.EndIfCommand{})
comp.Registry().Register(&commands.WhileCommand{})
comp.Registry().Register(&commands.BreakCommand{})
comp.Registry().Register(&commands.WendCommand{})
comp.Registry().Register(&commands.FuncCommand{})
comp.Registry().Register(commands.NewCallCommand(comp.Context().FunctionHandler))
comp.Registry().Register(&commands.FendCommand{})
comp.Registry().Register(&commands.IncrCommand{})
comp.Registry().Register(&commands.DecrCommand{})
comp.Registry().Register(&commands.GotoCommand{})
comp.Registry().Register(&commands.LabelCommand{})
comp.Registry().Register(&commands.OriginCommand{})
comp.Registry().Register(&commands.PointerCommand{})
comp.Registry().Register(&commands.PeekCommand{})
comp.Registry().Register(&commands.PeekWCommand{})
comp.Registry().Register(&commands.PokeCommand{})
comp.Registry().Register(&commands.PokeWCommand{})
comp.Registry().Register(&commands.SubEndCommand{})
comp.Registry().Register(&commands.GosubCommand{})
comp.Registry().Register(&commands.ForCommand{})
comp.Registry().Register(&commands.NextCommand{})
comp.Registry().Register(&commands.SwitchCommand{})
comp.Registry().Register(&commands.CaseCommand{})
comp.Registry().Register(&commands.DefaultCommand{})
comp.Registry().Register(&commands.EndSwitchCommand{})
}
func writeOutput(filename string, lines []string) error {
return os.WriteFile(filename, []byte(strings.Join(lines, "\n")+"\n"), 0644)
}