Added MultiIndex (replaces TMbsl in old version). Commented in main to make it compile
This commit is contained in:
parent
b251a7dd79
commit
63e321fd20
2 changed files with 254 additions and 17 deletions
57
internal/utils/multiindex.go
Normal file
57
internal/utils/multiindex.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MultiIndex[T any] struct {
|
||||||
|
items []T
|
||||||
|
indexes []map[string]*T
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMultiIndex[T any](numIndexes int) *MultiIndex[T] {
|
||||||
|
m := &MultiIndex[T]{
|
||||||
|
items: make([]T, 0),
|
||||||
|
indexes: make([]map[string]*T, numIndexes),
|
||||||
|
}
|
||||||
|
for i := range m.indexes {
|
||||||
|
m.indexes[i] = make(map[string]*T)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MultiIndex[T]) AddItem(item T, searchKeys [][]string) {
|
||||||
|
if len(searchKeys) != len(m.indexes) {
|
||||||
|
panic("searchKeys length must match number of indexes")
|
||||||
|
}
|
||||||
|
|
||||||
|
m.items = append(m.items, item)
|
||||||
|
itemPtr := &m.items[len(m.items)-1]
|
||||||
|
|
||||||
|
for i, key := range searchKeys {
|
||||||
|
m.indexes[i][keyToString(key)] = itemPtr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MultiIndex[T]) FindItem(indexNum int, key []string) (T, bool) {
|
||||||
|
var zero T
|
||||||
|
if indexNum < 0 || indexNum >= len(m.indexes) {
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
|
||||||
|
itemPtr, found := m.indexes[indexNum][keyToString(key)]
|
||||||
|
if !found {
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
return *itemPtr, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MultiIndex[T]) Items() []T {
|
||||||
|
result := make([]T, len(m.items))
|
||||||
|
copy(result, m.items)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyToString(parts []string) string {
|
||||||
|
return strings.Join(parts, "\x00")
|
||||||
|
}
|
||||||
214
main.go
214
main.go
|
|
@ -2,30 +2,210 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"c65gm/internal/preproc"
|
"c65gm/internal/preproc"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// put the DefineList type in another file (same package) or import it;
|
// c65cm - A 6502 Cross-Compiler for the ACME Cross-Assembler
|
||||||
// here I assume definelist.go is in its own package "definelist".
|
// Copyright (C) 1999, 2025 Mattias Hansson
|
||||||
// If it's in the same package main, just call New() directly.
|
// Distributed under GPL. External library github.com/armon/go-radix under MIT.
|
||||||
|
|
||||||
|
// Package-level shared state accessible by other compilation units
|
||||||
|
var (
|
||||||
|
/*
|
||||||
|
VarList *VarList
|
||||||
|
WhileStack *LabelStack
|
||||||
|
WendStack *LabelStack
|
||||||
|
IfStack *LabelStack
|
||||||
|
GeneralStack *LabelStack
|
||||||
|
FuncList *FunctionHandler
|
||||||
|
ConstStrHandler *ConstantStringHandler
|
||||||
|
Pragmas []string
|
||||||
|
*/
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShowMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ShowNone ShowMode = iota
|
||||||
|
ShowLineCount
|
||||||
|
ShowLineView
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defs := preproc.NewDefineList() // <-- important
|
fmt.Println("c65cm - A 6502 Cross-Compiler for the ACME Cross-Assembler.")
|
||||||
|
fmt.Println("Copyright (C) 1999, 2025 Mattias Hansson. v0.7")
|
||||||
|
fmt.Println("Distributed under GPL. External library github.com/armon/go-radix under MIT.")
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
defs.Add("ARRAY_MIN", "0")
|
inFile := flag.String("in", "", "input source file (required)")
|
||||||
defs.Add("ARRAY_MAX", "100")
|
outFile := flag.String("out", "", "output assembly file (required)")
|
||||||
defs.Add("ARRAY_MAX_PAX", "1000")
|
view := flag.String("view", "lines", "output mode: none, count, lines")
|
||||||
defs.Add("VERSION", "1.0")
|
flag.Parse()
|
||||||
defs.Add("π", "3.14159")
|
|
||||||
|
|
||||||
src := `for i := ARRAY_MIN to ARRAY_MAX_PAX do
|
if *inFile == "" || *outFile == "" {
|
||||||
writeln(VERSION);
|
fmt.Fprintln(os.Stderr, "Error: -in and -out are required")
|
||||||
writeln(ARRAY_MAX);
|
flag.Usage()
|
||||||
const PI = π;`
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Original:\n" + src)
|
var showMode ShowMode
|
||||||
fmt.Println("\nReplaced:\n" + defs.ReplaceDefines(src))
|
switch strings.ToLower(*view) {
|
||||||
defs.Delete("ARRAY_MAX_PAX")
|
case "none":
|
||||||
fmt.Println("\nReplaced (after .Delete):\n" + defs.ReplaceDefines(src))
|
showMode = ShowNone
|
||||||
|
case "count":
|
||||||
|
showMode = ShowLineCount
|
||||||
|
case "lines":
|
||||||
|
showMode = ShowLineView
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: invalid view mode: %s\n", *view)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := run(*inFile, *outFile, showMode); err != nil {
|
||||||
|
if _, ok := err.(preproc.HaltError); ok {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(inFile, outFile string, showMode ShowMode) error {
|
||||||
|
initSharedObjects()
|
||||||
|
return compile(inFile, outFile, showMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initSharedObjects() {
|
||||||
|
/*
|
||||||
|
VarList = NewVarList()
|
||||||
|
WhileStack = NewLabelStack("whilelbl")
|
||||||
|
WendStack = NewLabelStack("wendlbl")
|
||||||
|
IfStack = NewLabelStack("iflbl")
|
||||||
|
GeneralStack = NewLabelStack("General")
|
||||||
|
FuncList = NewFunctionHandler()
|
||||||
|
ConstStrHandler = NewConstantStringHandler()
|
||||||
|
Pragmas = make([]string, 0)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
func compile(inFile, outFile string, showMode ShowMode) error {
|
||||||
|
lines, err := preproc.PreProcess(inFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("preprocessor failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
asmSource := make([]string, 0, len(lines)*2)
|
||||||
|
lineCount := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(lines); {
|
||||||
|
line := lines[i]
|
||||||
|
lineCount++
|
||||||
|
|
||||||
|
displayProgress(showMode, lineCount, line.Text)
|
||||||
|
|
||||||
|
// Handle inline ASM blocks
|
||||||
|
if isAsmStart(line) {
|
||||||
|
asmSource = append(asmSource, ";"+line.Text)
|
||||||
|
i++
|
||||||
|
|
||||||
|
for i < len(lines) && !isAsmEnd(lines[i]) {
|
||||||
|
lineCount++
|
||||||
|
displayProgress(showMode, lineCount, lines[i].Text)
|
||||||
|
|
||||||
|
if lines[i].Text != "" {
|
||||||
|
//processed := LocalVarsInAsmLine(lines[i].Text)
|
||||||
|
processed := lines[i].Text
|
||||||
|
asmSource = append(asmSource, processed)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
i++ // Skip ENDASM line
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if isAsmEnd(line) {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
text := stripComments(line.Text)
|
||||||
|
if text == "" {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if !InterpretLine(text, &asmSource) {
|
||||||
|
return fmt.Errorf("line not recognized: %s", text)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
VarList.WriteDownTypesToAsm(&asmSource)
|
||||||
|
ConstStrHandler.GenerateConstStrDecls(&asmSource)
|
||||||
|
VarList.WriteAbsVars(&asmSource)
|
||||||
|
VarList.WriteConstants(&asmSource)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if err := writeLines(outFile, asmSource); err != nil {
|
||||||
|
return fmt.Errorf("failed to write output: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if showMode != ShowNone {
|
||||||
|
fmt.Println("\ndone.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func displayProgress(mode ShowMode, lineCount int, text string) {
|
||||||
|
switch mode {
|
||||||
|
case ShowLineCount:
|
||||||
|
fmt.Printf("\rCompiling line: %d", lineCount)
|
||||||
|
case ShowLineView:
|
||||||
|
fmt.Println(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAsmStart(line preproc.Line) bool {
|
||||||
|
//return len(line.Tokens) == 1 && strings.ToUpper(line.Tokens[0]) == "ASM"
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAsmEnd(line preproc.Line) bool {
|
||||||
|
//return len(line.Tokens) == 1 && strings.ToUpper(line.Tokens[0]) == "ENDASM"
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func stripComments(s string) string {
|
||||||
|
if strings.HasPrefix(s, "//") {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if idx := strings.Index(s, "//"); idx >= 0 {
|
||||||
|
return strings.TrimSpace(s[:idx])
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeLines(filename string, lines []string) error {
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
if _, err := fmt.Fprintln(f, line); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue