Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154package core
import ( "iter"
"git.urbach.dev/cli/q/src/config" "git.urbach.dev/cli/q/src/fs" "git.urbach.dev/cli/q/src/types")
// Environment holds information about the entire build.// Functions can access information about other functions using this.// We'll also pass this to the linker because it contains everything// that's needed to generate an executable file.type Environment struct { Build *config.Build Init *Function Main *Function Packages map[string]*Package Files []*fs.File NumFunctions int typeCache}
// AddPackage returns an existing package with the giving name or creates a new one.func (env *Environment) AddPackage(name string, isExtern bool) *Package { pkg, exists := env.Packages[name]
if !exists { pkg = &Package{ Name: name, Constants: make(map[string]*Constant), Enums: make(map[string]*types.Enum), Functions: make(map[string]*Function, 8), Structs: make(map[string]*types.Struct), Globals: make(map[string]*Global), IsExtern: isExtern, }
env.Packages[name] = pkg }
return pkg}
// Function looks up a function by the package name and raw function name.func (env *Environment) Function(pkgName string, name string) *Function { pkg, exists := env.Packages[pkgName]
if !exists { return nil }
fn, exists := pkg.Functions[name]
if !exists { return nil }
return fn}
// Functions returns an iterator over all functions.func (env *Environment) Functions() iter.Seq[*Function] { return func(yield func(*Function) bool) { for _, pkg := range env.Packages { for _, fn := range pkg.Functions { for variant := range fn.Variants { if !yield(variant) { return } } } } }}
// Globals returns an iterator over all globals.func (env *Environment) Globals() iter.Seq[*Global] { return func(yield func(*Global) bool) { for _, pkg := range env.Packages { for _, global := range pkg.Globals { if !yield(global) { return } } } }}
// LiveFunctions returns an iterator over functions that are alive,// starting with `run.init` and all of its dependencies.func (env *Environment) LiveFunctions() iter.Seq[*Function] { return func(yield func(*Function) bool) { var ( exit []*Function running = true traversed = make(map[*Function]bool, env.NumFunctions) )
env.Init.EachDependency(traversed, func(f *Function) { if !running { return }
if f.IsExit && f != env.Init { exit = append(exit, f) return }
running = yield(f) })
if !running { return }
for _, f := range exit { if !yield(f) { return } } }}
// Package resolves a package name for the given file and marks the import as used.func (env *Environment) Package(name string, file *fs.File) *Package { pkg, exists := env.Packages[name]
if exists && !pkg.IsExtern && pkg.Name != "main" { imp, exists := file.Imports[name]
if !exists { return nil }
imp.Used.Add(1) }
return pkg}
// Structs returns an iterator over all structs.func (env *Environment) Structs() iter.Seq[*types.Struct] { return func(yield func(*types.Struct) bool) { for _, pkg := range env.Packages { for _, structure := range pkg.Structs { if !yield(structure) { return } } } }}