Implemented directory walk

This commit is contained in:
Eduard Urbach 2023-10-20 15:29:40 +02:00
parent 0fe419da86
commit 886ea27d54
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
13 changed files with 100 additions and 20 deletions

View File

@ -5,9 +5,12 @@ import (
"bytes" "bytes"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"git.akyoto.dev/cli/q/build/elf" "git.akyoto.dev/cli/q/directory"
"git.akyoto.dev/cli/q/cli/log" "git.akyoto.dev/cli/q/elf"
"git.akyoto.dev/cli/q/errors"
"git.akyoto.dev/cli/q/log"
) )
// Build describes a compiler build. // Build describes a compiler build.
@ -43,30 +46,26 @@ func (build *Build) Run() error {
return nil return nil
} }
// Executable returns the path to the executable.
func (build *Build) Executable() string {
return filepath.Join(build.Directory, build.Name)
}
// Compile compiles all the functions. // Compile compiles all the functions.
func (build *Build) Compile() error { func (build *Build) Compile() error {
file, err := os.Open(build.Directory) stat, err := os.Stat(build.Directory)
if err != nil { if err != nil {
return err return err
} }
defer file.Close() if !stat.IsDir() {
files, err := file.Readdirnames(0) return &errors.InvalidDirectory{Path: build.Directory}
if err != nil {
return err
} }
for _, name := range files { directory.Walk(build.Directory, func(file string) {
log.Info.Println(name) if !strings.HasSuffix(file, ".q") {
return
} }
log.Info.Println(file)
})
build.Code.Write([]byte{ build.Code.Write([]byte{
0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1 0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1
0xbf, 0x01, 0x00, 0x00, 0x00, // mov edi, 1 0xbf, 0x01, 0x00, 0x00, 0x00, // mov edi, 1
@ -83,6 +82,11 @@ func (build *Build) Compile() error {
return nil 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. // writeToDisk writes the executable file to disk.
func writeToDisk(filePath string, code []byte, data []byte) error { func writeToDisk(filePath string, code []byte, data []byte) error {
file, err := os.Create(filePath) file, err := os.Create(filePath)

View File

@ -2,7 +2,7 @@ package cli
import ( import (
"git.akyoto.dev/cli/q/build" "git.akyoto.dev/cli/q/build"
"git.akyoto.dev/cli/q/cli/log" "git.akyoto.dev/cli/q/log"
) )
// Build builds an executable. // Build builds an executable.

View File

@ -1,7 +1,7 @@
package cli package cli
import ( import (
"git.akyoto.dev/cli/q/cli/log" "git.akyoto.dev/cli/q/log"
) )
// Help shows the command line argument usage. // Help shows the command line argument usage.

View File

@ -4,7 +4,7 @@ import (
"os" "os"
"runtime" "runtime"
"git.akyoto.dev/cli/q/cli/log" "git.akyoto.dev/cli/q/log"
) )
// System shows system information. // System shows system information.

View File

@ -6,7 +6,7 @@ import (
"testing" "testing"
"git.akyoto.dev/cli/q/cli" "git.akyoto.dev/cli/q/cli"
"git.akyoto.dev/cli/q/cli/log" "git.akyoto.dev/cli/q/log"
"git.akyoto.dev/go/assert" "git.akyoto.dev/go/assert"
) )

61
directory/Walk.go Normal file
View File

@ -0,0 +1,61 @@
package directory
import (
"syscall"
"unsafe"
)
const blockSize = 8 << 10
// Walk calls your callback function for every file name inside the directory.
// It doesn't distinguish between files and directories.
func Walk(directory string, callBack func(string)) {
fd, err := syscall.Open(directory, 0, 0)
if err != nil {
panic(err)
}
defer syscall.Close(fd)
buffer := make([]byte, blockSize)
for {
n, err := syscall.ReadDirent(fd, buffer)
if err != nil {
panic(err)
}
if n <= 0 {
break
}
readBuffer := buffer[:n]
for len(readBuffer) > 0 {
dirent := (*syscall.Dirent)(unsafe.Pointer(&readBuffer[0]))
readBuffer = readBuffer[dirent.Reclen:]
// Skip deleted files
if dirent.Ino == 0 {
continue
}
// Skip hidden files
if dirent.Name[0] == '.' {
continue
}
for i, c := range dirent.Name {
if c != 0 {
continue
}
bytePointer := (*byte)(unsafe.Pointer(&dirent.Name[0]))
name := unsafe.String(bytePointer, i)
callBack(name)
break
}
}
}
}

15
errors/InvalidPath.go Normal file
View File

@ -0,0 +1,15 @@
package errors
import "fmt"
type InvalidDirectory struct {
Path string
}
func (err *InvalidDirectory) Error() string {
if err.Path == "" {
return "Invalid directory"
}
return fmt.Sprintf("Invalid directory '%s'", err.Path)
}