From 5fb985ad2376b7c0d393b195ef5cfa2306ff2345 Mon Sep 17 00:00:00 2001 From: Michael McLoughlin Date: Tue, 6 Nov 2018 21:10:54 -0500 Subject: [PATCH] sketch --- ast.go | 53 ++++++++++++++++++++++++++++++++++ printer.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 ast.go create mode 100644 printer.go diff --git a/ast.go b/ast.go new file mode 100644 index 0000000..cb1c3f1 --- /dev/null +++ b/ast.go @@ -0,0 +1,53 @@ +package avo + +// GoType represents a Golang type. +type GoType interface{} + +// Parameter represents a parameter to an assembly function. +type Parameter struct { + Name string + Type GoType +} + +// Instruction is a single instruction in a function. +type Instruction struct { + Mnemonic string + Operands []string +} + +// File represents an assembly file. +type File struct { + functions []*Function +} + +// Function represents an assembly function. +type Function struct { + name string + params []Parameter + inst []Instruction +} + +func NewFunction(name string) *Function { + return &Function{ + name: name, + } +} + +func (f *Function) AddInstruction(i Instruction) { + f.inst = append(f.inst, i) +} + +// Name returns the function name. +func (f *Function) Name() string { return f.name } + +// FrameBytes returns the size of the stack frame in bytes. +func (f *Function) FrameBytes() int { + // TODO(mbm): implement + return 0 +} + +// ArgumentBytes returns the size of the arguments in bytes. +func (f *Function) ArgumentBytes() int { + // TODO(mbm): implement + return 0 +} diff --git a/printer.go b/printer.go new file mode 100644 index 0000000..19d7158 --- /dev/null +++ b/printer.go @@ -0,0 +1,85 @@ +package avo + +import ( + "fmt" + "io" + "strings" +) + +// dot is the pesky unicode dot used in Go assembly. +const dot = "\u00b7" + +type Printer interface { + Print(*File) error +} + +type GoPrinter struct { + w io.Writer + by string // generated by + copyright []string + err error +} + +func NewGoPrinter(w io.Writer) *GoPrinter { + return &GoPrinter{ + w: w, + by: "avo", + } +} + +func (p *GoPrinter) SetGeneratedBy(by string) { + p.by = by +} + +func (p *GoPrinter) Print(f *File) error { + p.header() + + for _, fn := range f.functions { + p.function(fn) + } + + return p.err +} + +func (p *GoPrinter) header() { + p.generated() + p.nl() + p.incl("textflag.h") + p.nl() +} + +func (p *GoPrinter) generated() { + p.comment(fmt.Sprintf("Code generated by %s. DO NOT EDIT.", p.by)) +} + +func (p *GoPrinter) incl(path string) { + p.printf("#include \"%s\"\n", path) +} + +func (p *GoPrinter) comment(line string) { + p.multicomment([]string{line}) +} + +func (p *GoPrinter) multicomment(lines []string) { + for _, line := range lines { + p.printf("// %s\n", line) + } +} + +func (p *GoPrinter) function(f *Function) { + p.printf("TEXT %s%s(SB),0,$%d-%d\n", dot, f.Name(), f.FrameBytes(), f.ArgumentBytes()) + + for _, i := range f.inst { + p.printf("\t%s\t%s\n", i.Mnemonic, strings.Join(i.Operands, ", ")) + } +} + +func (p *GoPrinter) nl() { + p.printf("\n") +} + +func (p *GoPrinter) printf(format string, args ...interface{}) { + if _, err := fmt.Fprintf(p.w, format, args...); err != nil { + p.err = err + } +}