package build import ( "bufio" "os" "path/filepath" "strings" "git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/directory" "git.akyoto.dev/cli/q/src/elf" "git.akyoto.dev/cli/q/src/errors" "git.akyoto.dev/cli/q/src/log" "git.akyoto.dev/cli/q/src/register" "git.akyoto.dev/cli/q/src/syscall" ) // Build describes a compiler build. type Build struct { Name string Directory string WriteExecutable bool } // New creates a new build. func New(directory string) *Build { return &Build{ Name: filepath.Base(directory), Directory: directory, WriteExecutable: true, } } // Run parses the input files and generates an executable file. func (build *Build) Run() error { // err := build.Compile() // if err != nil { // return err // } a := asm.New() a.MoveRegisterNumber(register.Syscall0, syscall.Write) a.MoveRegisterNumber(register.Syscall1, 1) a.MoveRegisterNumber(register.Syscall2, 0x4000a2) a.MoveRegisterNumber(register.Syscall3, 6) a.Syscall() a.MoveRegisterNumber(register.Syscall0, syscall.Exit) a.MoveRegisterNumber(register.Syscall1, 0) a.Syscall() result := a.Finalize() result.Data.WriteString("Hello\n") if !build.WriteExecutable { return nil } return writeToDisk(build.Executable(), result.Code.Bytes(), result.Data.Bytes()) } // Compile compiles all the functions. func (build *Build) Compile() error { stat, err := os.Stat(build.Directory) if err != nil { return err } if !stat.IsDir() { return &errors.InvalidDirectory{Path: build.Directory} } directory.Walk(build.Directory, func(file string) { if !strings.HasSuffix(file, ".q") { return } log.Info.Println(file) }) return nil } // Executable returns the path to the executable. func (build *Build) Executable() string { return filepath.Join(build.Directory, build.Name) } // writeToDisk writes the executable file to disk. func writeToDisk(filePath string, code []byte, data []byte) error { file, err := os.Create(filePath) if err != nil { return err } buffer := bufio.NewWriter(file) executable := elf.New(code, data) executable.Write(buffer) buffer.Flush() err = file.Close() if err != nil { return err } return os.Chmod(filePath, 0755) }