75 lines
1.4 KiB
Go
75 lines
1.4 KiB
Go
package compiler
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"git.akyoto.dev/cli/q/src/build/core"
|
|
"git.akyoto.dev/cli/q/src/build/errors"
|
|
)
|
|
|
|
// Compile waits for the scan to finish and compiles all functions.
|
|
func Compile(functions <-chan *core.Function, errs <-chan error) (Result, error) {
|
|
result := Result{}
|
|
all := map[string]*core.Function{}
|
|
|
|
for functions != nil || errs != nil {
|
|
select {
|
|
case err, ok := <-errs:
|
|
if !ok {
|
|
errs = nil
|
|
continue
|
|
}
|
|
|
|
return result, err
|
|
|
|
case function, ok := <-functions:
|
|
if !ok {
|
|
functions = nil
|
|
continue
|
|
}
|
|
|
|
function.Functions = all
|
|
all[function.Name] = function
|
|
}
|
|
}
|
|
|
|
// Start parallel compilation
|
|
CompileFunctions(all)
|
|
|
|
// Report errors if any occurred
|
|
for _, function := range all {
|
|
if function.Err != nil {
|
|
return result, function.Err
|
|
}
|
|
|
|
result.InstructionCount += len(function.Assembler.Instructions)
|
|
result.DataCount += len(function.Assembler.Data)
|
|
}
|
|
|
|
// Check for existence of `main`
|
|
main, exists := all["main"]
|
|
|
|
if !exists {
|
|
return result, errors.MissingMainFunction
|
|
}
|
|
|
|
result.Main = main
|
|
result.Functions = all
|
|
return result, nil
|
|
}
|
|
|
|
// CompileFunctions starts a goroutine for each function compilation and waits for completion.
|
|
func CompileFunctions(functions map[string]*core.Function) {
|
|
wg := sync.WaitGroup{}
|
|
|
|
for _, function := range functions {
|
|
wg.Add(1)
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
function.Compile()
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|