118 lines
3.7 KiB
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)
|
|
}
|