Added label and origin commands.
This commit is contained in:
parent
aedc605445
commit
5b3e5737b8
3 changed files with 112 additions and 1 deletions
48
internal/commands/label.go
Normal file
48
internal/commands/label.go
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"c65gm/internal/compiler"
|
||||||
|
"c65gm/internal/preproc"
|
||||||
|
"c65gm/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LabelCommand handles LABEL declarations
|
||||||
|
// Syntax: LABEL name
|
||||||
|
// Emits an assembly label for GOTO/GOSUB/CALL to target
|
||||||
|
type LabelCommand struct {
|
||||||
|
labelName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *LabelCommand) WillHandle(line preproc.Line) bool {
|
||||||
|
params, err := utils.ParseParams(line.Text)
|
||||||
|
if err != nil || len(params) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.ToUpper(params[0]) == "LABEL"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *LabelCommand) Interpret(line preproc.Line, _ *compiler.CompilerContext) error {
|
||||||
|
params, err := utils.ParseParams(line.Text)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params) != 2 {
|
||||||
|
return fmt.Errorf("LABEL: expected 2 parameters, got %d", len(params))
|
||||||
|
}
|
||||||
|
|
||||||
|
c.labelName = params[1]
|
||||||
|
|
||||||
|
if len(c.labelName) < 2 {
|
||||||
|
return fmt.Errorf("LABEL: label name must be at least 2 characters long")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *LabelCommand) Generate(_ *compiler.CompilerContext) ([]string, error) {
|
||||||
|
return []string{c.labelName}, nil
|
||||||
|
}
|
||||||
62
internal/commands/origin.go
Normal file
62
internal/commands/origin.go
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"c65gm/internal/compiler"
|
||||||
|
"c65gm/internal/preproc"
|
||||||
|
"c65gm/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OriginCommand handles ORIGIN declarations
|
||||||
|
// Syntax: ORIGIN <address>
|
||||||
|
// Sets the assembly origin address (ACME: *= address)
|
||||||
|
type OriginCommand struct {
|
||||||
|
address uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OriginCommand) WillHandle(line preproc.Line) bool {
|
||||||
|
params, err := utils.ParseParams(line.Text)
|
||||||
|
if err != nil || len(params) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
upper := strings.ToUpper(params[0])
|
||||||
|
return upper == "ORIGIN" || upper == "ORGIN" // Support common typo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OriginCommand) 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("ORIGIN: expected 2 parameters, 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
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := utils.EvaluateExpression(params[1], constLookup)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ORIGIN: invalid address expression: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if val < 0 || val > 65535 {
|
||||||
|
return fmt.Errorf("ORIGIN: address %d out of range (0-65535)", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.address = uint16(val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *OriginCommand) Generate(_ *compiler.CompilerContext) ([]string, error) {
|
||||||
|
return []string{fmt.Sprintf("*= $%04x", c.address)}, nil
|
||||||
|
}
|
||||||
3
main.go
3
main.go
|
|
@ -96,7 +96,8 @@ func registerCommands(comp *compiler.Compiler) {
|
||||||
comp.Registry().Register(&commands.IncrCommand{})
|
comp.Registry().Register(&commands.IncrCommand{})
|
||||||
comp.Registry().Register(&commands.DecrCommand{})
|
comp.Registry().Register(&commands.DecrCommand{})
|
||||||
comp.Registry().Register(&commands.GotoCommand{})
|
comp.Registry().Register(&commands.GotoCommand{})
|
||||||
|
comp.Registry().Register(&commands.LabelCommand{})
|
||||||
|
comp.Registry().Register(&commands.OriginCommand{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeOutput(filename string, lines []string) error {
|
func writeOutput(filename string, lines []string) error {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue