go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit 01301ae35765d89b988a3ac5d9c520e93b045e37
parent dfaf29bf00e52b69b8ed9e164822d55d4c91fbb0
Author: lash <dev@holbrook.no>
Date:   Mon, 26 Aug 2024 18:34:56 +0100

Handle both CROAK and CATCH in preprocessor

Diffstat:
Mdev/asm/main.go | 134++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 109 insertions(+), 25 deletions(-)

diff --git a/dev/asm/main.go b/dev/asm/main.go @@ -1,7 +1,10 @@ package main import ( + "encoding/csv" + "flag" "fmt" + "io" "io/ioutil" "log" "os" @@ -32,7 +35,75 @@ type asmAsm struct { Instructions []*instruction `@@*` } -func preProcess(b []byte) ([]byte, error) { +type preProcessor struct { + flags map[string]string +} + +func newPreProcessor() *preProcessor { + return &preProcessor{ + flags: make(map[string]string), + } +} + +func(pp *preProcessor) load(fp string) (int, error) { + var i int + f, err := os.Open(fp) + if err != nil { + return 0, err + } + defer f.Close() + r := csv.NewReader(f) + for i = 0; true; i++ { + r, err := r.Read() + if err != nil { + if err == io.EOF { + break + } + return 0, err + } + if r[0] == "flag" { + if len(r) < 3 { + return 0, fmt.Errorf("Not enough fields for flag setting in line %d", i) + } + _, err = strconv.Atoi(r[2]) + if err != nil { + return 0, fmt.Errorf("Flag translation value must be numeric") + } + pp.flags[r[1]] = r[2] + log.Printf("added flag translation %s -> %s", r[1], r[2]) + } + } + + return i, nil +} + + +func(pp *preProcessor) processFlag(s []string, one *string, two *string) ([]string, error) { + _, err := strconv.Atoi(*one) + if err != nil { + r, ok := pp.flags[*one] + if !ok { + return nil, fmt.Errorf("No flag translation found for '%s'", *one) + } + log.Printf("translated flag %s to %s", *one, r) + s = append(s, r) + } else { + s = append(s, *one) + } + return append(s, *two), nil +} + +func(pp *preProcessor) pass(s []string, a arg) []string { + for _, r := range []*string{a.One, a.Two, a.Three} { + if r == nil { + break + } + s = append(s, *r) + } + return s +} + +func(pp *preProcessor) run(b []byte) ([]byte, error) { asmLexer := lexer.MustSimple([]lexer.SimpleRule{ {"Comment", `(?:#)[^\n]*`}, {"Ident", `^[A-Z]+`}, @@ -53,22 +124,24 @@ func preProcess(b []byte) ([]byte, error) { b = []byte{} for _, v := range ast.Instructions { - s := []string{v.OpCode, *v.OpArg.One} - if v.OpCode == "CATCH" { - _, err := strconv.Atoi(*v.OpArg.Two) - if err != nil { - s = append(s, "42") - } else { - s = append(s, *v.OpArg.Two) - } - s = append(s, *v.OpArg.Three) - } else { - for _, r := range []*string{v.OpArg.Two, v.OpArg.Three} { - if r == nil { - break + s := []string{v.OpCode} + if v.OpArg.One == nil { + continue + } + switch v.OpCode { + case "CATCH": + s = append(s, *v.OpArg.One) + s, err = pp.processFlag(s, v.OpArg.Two, v.OpArg.Three) + if err != nil { + return nil, err } - s = append(s, *r) - } + case "CROAK": + s, err = pp.processFlag(s, v.OpArg.One, v.OpArg.Two) + if err != nil { + return nil, err + } + default: + s = pp.pass(s, v.OpArg) } b = append(b, []byte(strings.Join(s, " "))...) b = append(b, 0x0a) @@ -78,27 +151,38 @@ func preProcess(b []byte) ([]byte, error) { } func main() { - if (len(os.Args) < 2) { + var ppfp string + flag.StringVar(&ppfp, "f", "", "preprocessor data to load") + flag.Parse() + if (len(flag.Args()) < 1) { os.Exit(1) } - fp := os.Args[1] + fp := flag.Arg(0) v, err := ioutil.ReadFile(fp) if err != nil { - fmt.Fprintf(os.Stderr, "read error: %v", err) + fmt.Fprintf(os.Stderr, "read error: %v\n", err) os.Exit(1) } - log.Printf("start preprocessor") - v, err = preProcess(v) - if err != nil { - fmt.Fprintf(os.Stderr, "preprocess error: %v", err) - os.Exit(1) + if len(ppfp) > 0 { + pp := newPreProcessor() + _, err := pp.load(ppfp) + if err != nil { + fmt.Fprintf(os.Stderr, "preprocessor load error: %v\n", err) + os.Exit(1) + } + + v, err = pp.run(v) + if err != nil { + fmt.Fprintf(os.Stderr, "preprocess error: %v\n", err) + os.Exit(1) + } } log.Printf("preprocessor done") n, err := asm.Parse(string(v), os.Stdout) if err != nil { - fmt.Fprintf(os.Stderr, "parse error: %v", err) + fmt.Fprintf(os.Stderr, "parse error: %v\n", err) os.Exit(1) } log.Printf("parsed total %v bytes", n)