q/src/core/Function.go
Eduard Urbach a1f6c66736
All checks were successful
/ test (push) Successful in 15s
Added ssa tests
2025-06-30 13:35:24 +02:00

79 lines
No EOL
1.8 KiB
Go

package core
import (
"fmt"
"git.urbach.dev/cli/q/src/asm"
"git.urbach.dev/cli/q/src/cpu"
"git.urbach.dev/cli/q/src/fs"
"git.urbach.dev/cli/q/src/set"
"git.urbach.dev/cli/q/src/ssa"
"git.urbach.dev/cli/q/src/token"
"git.urbach.dev/cli/q/src/types"
)
// Function is the smallest unit of code.
type Function struct {
ssa.IR
Name string
UniqueName string
File *fs.File
Input []*ssa.Parameter
Output []*ssa.Parameter
Body token.List
Identifiers map[string]ssa.Value
All *Environment
Dependencies set.Ordered[*Function]
Assembler asm.Assembler
CPU *cpu.CPU
Type *types.Function
Err error
}
// NewFunction creates a new function.
func NewFunction(name string, file *fs.File) *Function {
return &Function{
Name: name,
File: file,
UniqueName: fmt.Sprintf("%s.%s", file.Package, name),
Identifiers: make(map[string]ssa.Value, 8),
IR: ssa.IR{
Blocks: []*ssa.Block{
{Instructions: make([]ssa.Value, 0, 8)},
},
},
Assembler: asm.Assembler{
Instructions: make([]asm.Instruction, 0, 8),
},
}
}
// EachDependency recursively finds all the calls to other functions.
// It avoids calling the same function twice with the help of a hashmap.
func (f *Function) EachDependency(traversed map[*Function]bool, call func(*Function)) {
call(f)
traversed[f] = true
for dep := range f.Dependencies.All() {
if traversed[dep] {
continue
}
dep.EachDependency(traversed, call)
}
}
// IsExtern returns true if the function has no body.
func (f *Function) IsExtern() bool {
return f.Body == nil
}
// IsLeaf returns true if the function doesn't call other functions.
func (f *Function) IsLeaf() bool {
return f.Dependencies.Count() == 0
}
// String returns the unique name.
func (f *Function) String() string {
return f.UniqueName
}