Implemented environment type

This commit is contained in:
Eduard Urbach 2025-02-21 17:35:42 +01:00
parent 4caac57210
commit 91e01de3ad
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
15 changed files with 67 additions and 51 deletions

View File

@ -9,7 +9,7 @@ type compiler struct {
dataLabels map[string]Address dataLabels map[string]Address
codePointers []*pointer codePointers []*pointer
dataPointers []*pointer dataPointers []*pointer
codeStart Address
dlls dll.List
dllPointers []*pointer dllPointers []*pointer
dlls dll.List
codeStart Address
} }

View File

@ -9,11 +9,14 @@ import (
// Compile waits for the scan to finish and compiles all functions. // Compile waits for the scan to finish and compiles all functions.
func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <-chan *core.Function, structs <-chan *types.Struct, errs <-chan error) (Result, error) { func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <-chan *core.Function, structs <-chan *types.Struct, errs <-chan error) (Result, error) {
all := core.Environment{
Files: make([]*fs.File, 0, 8),
Functions: make(map[string]*core.Function, 32),
Structs: make(map[string]*types.Struct, 8),
Constants: make(map[string]*core.Constant, 8),
}
result := Result{} result := Result{}
allFiles := make([]*fs.File, 0, 8)
allFunctions := make(map[string]*core.Function, 32)
allStructs := make(map[string]*types.Struct, 8)
allConstants := make(map[string]*core.Constant, 8)
for constants != nil || files != nil || functions != nil || structs != nil || errs != nil { for constants != nil || files != nil || functions != nil || structs != nil || errs != nil {
select { select {
@ -23,10 +26,8 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue continue
} }
function.Functions = allFunctions function.All = &all
function.Structs = allStructs all.Functions[function.UniqueName] = function
function.Constants = allConstants
allFunctions[function.UniqueName] = function
case structure, ok := <-structs: case structure, ok := <-structs:
if !ok { if !ok {
@ -34,7 +35,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue continue
} }
allStructs[structure.UniqueName] = structure all.Structs[structure.UniqueName] = structure
case file, ok := <-files: case file, ok := <-files:
if !ok { if !ok {
@ -42,7 +43,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue continue
} }
allFiles = append(allFiles, file) all.Files = append(all.Files, file)
case constant, ok := <-constants: case constant, ok := <-constants:
if !ok { if !ok {
@ -50,7 +51,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue continue
} }
allConstants[constant.Name] = constant all.Constants[constant.Name] = constant
case err, ok := <-errs: case err, ok := <-errs:
if !ok { if !ok {
@ -63,12 +64,12 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
} }
// Calculate size of structs // Calculate size of structs
for _, structure := range allStructs { for _, structure := range all.Structs {
structure.Update(allStructs) structure.Update(all.Structs)
} }
// Resolve the types // Resolve the types
for _, function := range allFunctions { for _, function := range all.Functions {
err := function.ResolveTypes() err := function.ResolveTypes()
if err != nil { if err != nil {
@ -77,10 +78,10 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
} }
// Start parallel compilation // Start parallel compilation
CompileFunctions(allFunctions) CompileFunctions(all.Functions)
// Report errors if any occurred // Report errors if any occurred
for _, function := range allFunctions { for _, function := range all.Functions {
if function.Err != nil { if function.Err != nil {
return result, function.Err return result, function.Err
} }
@ -90,7 +91,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
} }
// Check for unused imports in all files // Check for unused imports in all files
for _, file := range allFiles { for _, file := range all.Files {
for _, pkg := range file.Imports { for _, pkg := range file.Imports {
if !pkg.Used { if !pkg.Used {
return result, errors.New(&errors.UnusedImport{Package: pkg.Path}, file, pkg.Position) return result, errors.New(&errors.UnusedImport{Package: pkg.Path}, file, pkg.Position)
@ -99,14 +100,14 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
} }
// Check for existence of `init` // Check for existence of `init`
init, exists := allFunctions["core.init"] init, exists := all.Functions["core.init"]
if !exists { if !exists {
return result, errors.MissingInitFunction return result, errors.MissingInitFunction
} }
// Check for existence of `main` // Check for existence of `main`
main, exists := allFunctions["main.main"] main, exists := all.Functions["main.main"]
if !exists { if !exists {
return result, errors.MissingMainFunction return result, errors.MissingMainFunction
@ -114,7 +115,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
result.Init = init result.Init = init
result.Main = main result.Main = main
result.Functions = allFunctions result.Functions = all.Functions
result.finalize() result.finalize()
return result, nil return result, nil
} }

View File

@ -11,9 +11,9 @@ type Result struct {
Main *core.Function Main *core.Function
Functions map[string]*core.Function Functions map[string]*core.Function
Traversed map[*core.Function]bool Traversed map[*core.Function]bool
InstructionCount int
DataCount int
Code []byte Code []byte
Data []byte Data []byte
DLLs dll.List DLLs dll.List
InstructionCount int
DataCount int
} }

View File

@ -49,7 +49,7 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
return nil, nil return nil, nil
} }
fn, exists = f.Functions[pkg+"."+name] fn, exists = f.All.Functions[pkg+"."+name]
if !exists { if !exists {
return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position) return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position)

View File

@ -22,6 +22,6 @@ func (f *Function) CompileDelete(root *expression.Expression) error {
f.SaveRegister(f.CPU.Input[1]) f.SaveRegister(f.CPU.Input[1])
f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Register) f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Register)
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Type.(*types.Pointer).To.Size()) f.RegisterNumber(asm.MOVE, f.CPU.Input[1], variable.Type.(*types.Pointer).To.Size())
f.CallSafe(f.Functions["mem.free"], f.CPU.Input[:2]) f.CallSafe(f.All.Functions["mem.free"], f.CPU.Input[:2])
return nil return nil
} }

View File

@ -37,7 +37,7 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
imp.Used = true imp.Used = true
} }
typ, exists := f.Structs[pkg+"."+name] typ, exists := f.All.Structs[pkg+"."+name]
if !exists { if !exists {
return nil, errors.New(&errors.UnknownType{Name: name}, f.File, nameNode.Token.Position) return nil, errors.New(&errors.UnknownType{Name: name}, f.File, nameNode.Token.Position)
@ -45,6 +45,6 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
f.SaveRegister(f.CPU.Input[0]) f.SaveRegister(f.CPU.Input[0])
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size()) f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
f.CallSafe(f.Functions["mem.alloc"], f.CPU.Input[:1]) f.CallSafe(f.All.Functions["mem.alloc"], f.CPU.Input[:1])
return &types.Pointer{To: typ}, nil return &types.Pointer{To: typ}, nil
} }

View File

@ -7,7 +7,7 @@ import (
// Constant registers a single value to be accessible under a descriptive name. // Constant registers a single value to be accessible under a descriptive name.
type Constant struct { type Constant struct {
File *fs.File
Name string Name string
Token token.Token Token token.Token
File *fs.File
} }

View File

@ -6,11 +6,11 @@ import (
) )
// CreateLabel creates a label that is tied to this function by using a suffix. // CreateLabel creates a label that is tied to this function by using a suffix.
func (f *Function) CreateLabel(prefix string, count int) string { func (f *Function) CreateLabel(prefix string, count uint16) string {
tmp := strings.Builder{} tmp := strings.Builder{}
tmp.WriteString(prefix) tmp.WriteString(prefix)
tmp.WriteString(" ") tmp.WriteString(" ")
tmp.WriteString(strconv.Itoa(count)) tmp.WriteString(strconv.FormatUint(uint64(count), 10))
tmp.WriteString(" [") tmp.WriteString(" [")
tmp.WriteString(f.UniqueName) tmp.WriteString(f.UniqueName)
tmp.WriteString("]") tmp.WriteString("]")

14
src/core/Environment.go Normal file
View File

@ -0,0 +1,14 @@
package core
import (
"git.akyoto.dev/cli/q/src/fs"
"git.akyoto.dev/cli/q/src/types"
)
// Environment holds information about the entire build.
type Environment struct {
Constants map[string]*Constant
Functions map[string]*Function
Structs map[string]*types.Struct
Files []*fs.File
}

View File

@ -32,7 +32,7 @@ func (f *Function) Fold(expr *expression.Expression) error {
leftText := left.Token.Text(f.File.Bytes) leftText := left.Token.Text(f.File.Bytes)
right := expr.Children[1] right := expr.Children[1]
rightText := right.Token.Text(f.File.Bytes) rightText := right.Token.Text(f.File.Bytes)
constant, isConst := f.Constants[f.Package+"."+leftText+"."+rightText] constant, isConst := f.All.Constants[f.Package+"."+leftText+"."+rightText]
if !isConst { if !isConst {
return nil return nil

View File

@ -14,26 +14,14 @@ type Function struct {
Package string Package string
Name string Name string
UniqueName string UniqueName string
All *Environment
File *fs.File File *fs.File
Body token.List Body token.List
Input []*Parameter Input []*Parameter
Output []*Parameter Output []*Parameter
OutputTypes []types.Type OutputTypes []types.Type
Functions map[string]*Function
Structs map[string]*types.Struct
Constants map[string]*Constant
DLLs dll.List DLLs dll.List
Err error Err error
deferred []func() deferred []func()
count counter count count
}
// counter stores how often a certain statement appeared so we can generate a unique label from it.
type counter struct {
assert int
branch int
multiBranch int
data int
loop int
subBranch int
} }

View File

@ -15,7 +15,7 @@ func (f *Function) Identifier(name string) (*scope.Variable, *Function) {
} }
uniqueName := fmt.Sprintf("%s.%s", f.Package, name) uniqueName := fmt.Sprintf("%s.%s", f.Package, name)
function, exists := f.Functions[uniqueName] function, exists := f.All.Functions[uniqueName]
if exists { if exists {
return nil, function return nil, function

View File

@ -33,7 +33,7 @@ func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Re
return field.Type, nil return field.Type, nil
} }
constant, isConst := f.Constants[f.Package+"."+leftText+"."+rightText] constant, isConst := f.All.Constants[f.Package+"."+leftText+"."+rightText]
if isConst { if isConst {
number, err := ToNumber(constant.Token, constant.File) number, err := ToNumber(constant.Token, constant.File)
@ -48,7 +48,7 @@ func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Re
} }
uniqueName := fmt.Sprintf("%s.%s", leftText, rightText) uniqueName := fmt.Sprintf("%s.%s", leftText, rightText)
function, exists := f.Functions[uniqueName] function, exists := f.All.Functions[uniqueName]
if exists { if exists {
f.File.Imports[leftText].Used = true f.File.Imports[leftText].Used = true

View File

@ -13,7 +13,7 @@ func (f *Function) ResolveTypes() error {
for i, param := range f.Input { for i, param := range f.Input {
param.name = param.tokens[0].Text(f.File.Bytes) param.name = param.tokens[0].Text(f.File.Bytes)
typeName := param.tokens[1:].Text(f.File.Bytes) typeName := param.tokens[1:].Text(f.File.Bytes)
param.typ = types.ByName(typeName, f.Package, f.Structs) param.typ = types.ByName(typeName, f.Package, f.All.Structs)
if param.typ == nil { if param.typ == nil {
return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[1].Position) return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[1].Position)
@ -39,7 +39,7 @@ func (f *Function) ResolveTypes() error {
for _, param := range f.Output { for _, param := range f.Output {
typeName := param.tokens.Text(f.File.Bytes) typeName := param.tokens.Text(f.File.Bytes)
param.typ = types.ByName(typeName, f.Package, f.Structs) param.typ = types.ByName(typeName, f.Package, f.All.Structs)
if param.typ == nil { if param.typ == nil {
return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[0].Position) return errors.New(&errors.UnknownType{Name: typeName}, f.File, param.tokens[0].Position)

13
src/core/count.go Normal file
View File

@ -0,0 +1,13 @@
package core
type counter = uint16
// count stores how often a certain statement appeared so we can generate a unique label from it.
type count struct {
assert counter
branch counter
multiBranch counter
data counter
loop counter
subBranch counter
}