Added support for single file builds

This commit is contained in:
Eduard Urbach 2024-06-12 12:10:29 +02:00
parent ef11656e47
commit 2d990b0bee
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
4 changed files with 57 additions and 24 deletions

View File

@ -2,25 +2,27 @@ package build
import (
"path/filepath"
"strings"
)
// Build describes a compiler build.
type Build struct {
Directory string
Files []string
WriteExecutable bool
}
// New creates a new build.
func New(directory string) *Build {
func New(files ...string) *Build {
return &Build{
Directory: directory,
Files: files,
WriteExecutable: true,
}
}
// Run parses the input files and generates an executable file.
func (build *Build) Run() error {
functions, err := Compile(build.Directory)
functions, errors := Scan(build.Files)
allFunctions, err := Compile(functions, errors)
if err != nil {
return err
@ -31,11 +33,17 @@ func (build *Build) Run() error {
}
path := build.Executable()
code, data := Finalize(functions)
code, data := Finalize(allFunctions)
return Write(path, code, data)
}
// Executable returns the path to the executable.
func (build *Build) Executable() string {
return filepath.Join(build.Directory, filepath.Base(build.Directory))
directory, _ := filepath.Abs(build.Files[0])
if strings.HasSuffix(directory, ".q") {
directory = filepath.Dir(directory)
}
return filepath.Join(directory, filepath.Base(directory))
}

View File

@ -5,8 +5,7 @@ import (
)
// Compile compiles all the functions.
func Compile(directory string) (map[string]*Function, error) {
functions, errors := Scan(directory)
func Compile(functions <-chan *Function, errors <-chan error) (map[string]*Function, error) {
wg := sync.WaitGroup{}
allFunctions := map[string]*Function{}

View File

@ -11,12 +11,12 @@ import (
)
// Scan scans the directory.
func Scan(path string) (<-chan *Function, <-chan error) {
func Scan(files []string) (<-chan *Function, <-chan error) {
functions := make(chan *Function)
errors := make(chan error)
go func() {
scan(path, functions, errors)
scan(files, functions, errors)
close(functions)
close(errors)
}()
@ -25,15 +25,24 @@ func Scan(path string) (<-chan *Function, <-chan error) {
}
// scan scans the directory without channel allocations.
func scan(path string, functions chan<- *Function, errors chan<- error) {
func scan(files []string, functions chan<- *Function, errors chan<- error) {
wg := sync.WaitGroup{}
err := directory.Walk(path, func(name string) {
for _, file := range files {
stat, err := os.Stat(file)
if err != nil {
errors <- err
return
}
if stat.IsDir() {
err = directory.Walk(file, func(name string) {
if !strings.HasSuffix(name, ".q") {
return
}
fullPath := filepath.Join(path, name)
fullPath := filepath.Join(file, name)
wg.Add(1)
go func() {
@ -49,6 +58,19 @@ func scan(path string, functions chan<- *Function, errors chan<- error) {
if err != nil {
errors <- err
}
} else {
wg.Add(1)
go func() {
defer wg.Done()
err := scanFile(file, functions)
if err != nil {
errors <- err
}
}()
}
}
wg.Wait()
}

View File

@ -10,7 +10,7 @@ import (
// Build builds an executable.
func Build(args []string) int {
b := build.New(".")
b := build.New()
for i := 0; i < len(args); i++ {
switch args[i] {
@ -26,10 +26,14 @@ func Build(args []string) int {
return 2
}
b.Directory = args[i]
b.Files = append(b.Files, args[i])
}
}
if len(b.Files) == 0 {
b.Files = append(b.Files, ".")
}
err := b.Run()
if err != nil {