mirror of
https://github.com/RoBaertschi/tt.git
synced 2025-06-05 03:03:28 +00:00
compiler compile
This commit is contained in:
parent
28d464f318
commit
6513c45936
@ -22,7 +22,7 @@ func TestOperands(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCodegen(t *testing.T) {
|
func TestCodegen(t *testing.T) {
|
||||||
program := ttir.Program{
|
program := &ttir.Program{
|
||||||
Functions: []ttir.Function{
|
Functions: []ttir.Function{
|
||||||
{
|
{
|
||||||
Name: "main",
|
Name: "main",
|
||||||
|
90
cmd/cmd.go
90
cmd/cmd.go
@ -1,10 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -16,6 +18,54 @@ import (
|
|||||||
"robaertschi.xyz/robaertschi/tt/typechecker"
|
"robaertschi.xyz/robaertschi/tt/typechecker"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type prefixWriter struct {
|
||||||
|
output io.Writer
|
||||||
|
outputPrefix []byte
|
||||||
|
outputPrefixWritten bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPrefixWriter(output io.Writer, prefix []byte) *prefixWriter {
|
||||||
|
return &prefixWriter{
|
||||||
|
output: output,
|
||||||
|
outputPrefix: prefix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPrefixWriterString(output io.Writer, prefix string) *prefixWriter {
|
||||||
|
return &prefixWriter{
|
||||||
|
output: output,
|
||||||
|
outputPrefix: []byte(prefix),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *prefixWriter) Write(p []byte) (n int, err error) {
|
||||||
|
|
||||||
|
toWrites := bytes.SplitAfter(p, []byte{'\n'})
|
||||||
|
|
||||||
|
for _, toWrite := range toWrites {
|
||||||
|
if len(toWrite) <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !w.outputPrefixWritten {
|
||||||
|
w.outputPrefixWritten = true
|
||||||
|
w.output.Write(w.outputPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Contains(toWrite, []byte{'\n'}) {
|
||||||
|
w.outputPrefixWritten = false
|
||||||
|
}
|
||||||
|
|
||||||
|
var written int
|
||||||
|
written, err = w.output.Write(toWrite)
|
||||||
|
n += written
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s [flags] input\nPossible flags:\n", os.Args[0])
|
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s [flags] input\nPossible flags:\n", os.Args[0])
|
||||||
@ -25,6 +75,7 @@ func main() {
|
|||||||
var output string
|
var output string
|
||||||
flag.StringVar(&output, "o", "", "Output a executable named `file`")
|
flag.StringVar(&output, "o", "", "Output a executable named `file`")
|
||||||
flag.StringVar(&output, "output", "", "Output a executable named `file`")
|
flag.StringVar(&output, "output", "", "Output a executable named `file`")
|
||||||
|
onlyEmitAsm := flag.Bool("S", false, "Only emit the asembly file and exit")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
input := flag.Arg(0)
|
input := flag.Arg(0)
|
||||||
@ -34,9 +85,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if output == "" {
|
if output == "" {
|
||||||
output = strings.TrimRight(input, filepath.Ext(input))
|
output = strings.TrimSuffix(input, filepath.Ext(input))
|
||||||
}
|
}
|
||||||
asmOutputName := strings.TrimRight(input, filepath.Ext(input)) + ".asm"
|
asmOutputName := strings.TrimSuffix(input, filepath.Ext(input)) + ".asm"
|
||||||
|
|
||||||
file, err := os.Open(input)
|
file, err := os.Open(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -85,16 +136,43 @@ func main() {
|
|||||||
|
|
||||||
asmOutput := asm.Emit()
|
asmOutput := asm.Emit()
|
||||||
|
|
||||||
asmOutputFile, err := os.Open(asmOutputName)
|
asmOutputFile, err := os.Create(asmOutputName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to open asm file %q because: %e", asmOutputName, err)
|
fmt.Printf("Failed to create/truncate asm file %q because: %v\n", asmOutputName, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer asmOutputFile.Close()
|
|
||||||
|
|
||||||
_, err = asmOutputFile.WriteString(asmOutput)
|
_, err = asmOutputFile.WriteString(asmOutput)
|
||||||
|
asmOutputFile.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to write to file %q because: %e", asmOutputName, err)
|
fmt.Printf("Failed to write to file %q because: %v\n", asmOutputName, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fasmPath, err := exec.LookPath("fasm")
|
||||||
|
if err != nil {
|
||||||
|
fasmPath, err = exec.LookPath("fasm2")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Could not find fasm or fasm2, please install any those two using your systems package manager or from https://flatassembler.net\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !*onlyEmitAsm {
|
||||||
|
args := []string{asmOutputName, output}
|
||||||
|
cmd := exec.Command(fasmPath, args...)
|
||||||
|
cmd.Stdout = NewPrefixWriterString(os.Stdout, "fasm output: ")
|
||||||
|
cmd.Stderr = cmd.Stdout
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to run fasm because: %v\nCheck the asm file %q for errors and report these to the author!\n", err, asmOutputName)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeErr := os.Remove(asmOutputName)
|
||||||
|
if removeErr != nil {
|
||||||
|
fmt.Printf("Failed to remove %q file, please remove it yourself. Err: %v\n", asmOutputName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,6 @@ func (p *Parser) registerPrefixFn(tt token.TokenType, fn prefixParseFn) {
|
|||||||
func (p *Parser) nextToken() {
|
func (p *Parser) nextToken() {
|
||||||
p.curToken = p.peekToken
|
p.curToken = p.peekToken
|
||||||
p.peekToken = p.l.NextToken()
|
p.peekToken = p.l.NextToken()
|
||||||
fmt.Printf("curToken: %q, peekToken: %q\n", p.curToken.Type, p.peekToken.Type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) curTokenIs(tt token.TokenType) bool {
|
func (p *Parser) curTokenIs(tt token.TokenType) bool {
|
||||||
|
13
test.asm
13
test.asm
@ -1,13 +0,0 @@
|
|||||||
format ELF64 executable
|
|
||||||
|
|
||||||
segment readable executable
|
|
||||||
main:
|
|
||||||
mov rax, 0
|
|
||||||
ret
|
|
||||||
|
|
||||||
entry _start
|
|
||||||
_start:
|
|
||||||
call main
|
|
||||||
mov rdi, rax
|
|
||||||
mov rax, 60
|
|
||||||
syscall
|
|
Loading…
x
Reference in New Issue
Block a user