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
codePointers []*pointer
dataPointers []*pointer
codeStart Address
dlls dll.List
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.
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{}
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 {
select {
@ -23,10 +26,8 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue
}
function.Functions = allFunctions
function.Structs = allStructs
function.Constants = allConstants
allFunctions[function.UniqueName] = function
function.All = &all
all.Functions[function.UniqueName] = function
case structure, ok := <-structs:
if !ok {
@ -34,7 +35,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue
}
allStructs[structure.UniqueName] = structure
all.Structs[structure.UniqueName] = structure
case file, ok := <-files:
if !ok {
@ -42,7 +43,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue
}
allFiles = append(allFiles, file)
all.Files = append(all.Files, file)
case constant, ok := <-constants:
if !ok {
@ -50,7 +51,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
continue
}
allConstants[constant.Name] = constant
all.Constants[constant.Name] = constant
case err, ok := <-errs:
if !ok {
@ -63,12 +64,12 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
}
// Calculate size of structs
for _, structure := range allStructs {
structure.Update(allStructs)
for _, structure := range all.Structs {
structure.Update(all.Structs)
}
// Resolve the types
for _, function := range allFunctions {
for _, function := range all.Functions {
err := function.ResolveTypes()
if err != nil {
@ -77,10 +78,10 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
}
// Start parallel compilation
CompileFunctions(allFunctions)
CompileFunctions(all.Functions)
// Report errors if any occurred
for _, function := range allFunctions {
for _, function := range all.Functions {
if function.Err != nil {
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
for _, file := range allFiles {
for _, file := range all.Files {
for _, pkg := range file.Imports {
if !pkg.Used {
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`
init, exists := allFunctions["core.init"]
init, exists := all.Functions["core.init"]
if !exists {
return result, errors.MissingInitFunction
}
// Check for existence of `main`
main, exists := allFunctions["main.main"]
main, exists := all.Functions["main.main"]
if !exists {
return result, errors.MissingMainFunction
@ -114,7 +115,7 @@ func Compile(constants <-chan *core.Constant, files <-chan *fs.File, functions <
result.Init = init
result.Main = main
result.Functions = allFunctions
result.Functions = all.Functions
result.finalize()
return result, nil
}

View File

@ -11,9 +11,9 @@ type Result struct {
Main *core.Function
Functions map[string]*core.Function
Traversed map[*core.Function]bool
InstructionCount int
DataCount int
Code []byte
Data []byte
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
}
fn, exists = f.Functions[pkg+"."+name]
fn, exists = f.All.Functions[pkg+"."+name]
if !exists {
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.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Register)
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
}

View File

@ -37,7 +37,7 @@ func (f *Function) CompileNew(root *expression.Expression) (types.Type, error) {
imp.Used = true
}
typ, exists := f.Structs[pkg+"."+name]
typ, exists := f.All.Structs[pkg+"."+name]
if !exists {
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.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
}

View File

@ -7,7 +7,7 @@ import (
// Constant registers a single value to be accessible under a descriptive name.
type Constant struct {
File *fs.File
Name string
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.
func (f *Function) CreateLabel(prefix string, count int) string {
func (f *Function) CreateLabel(prefix string, count uint16) string {
tmp := strings.Builder{}
tmp.WriteString(prefix)
tmp.WriteString(" ")
tmp.WriteString(strconv.Itoa(count))
tmp.WriteString(strconv.FormatUint(uint64(count), 10))
tmp.WriteString(" [")
tmp.WriteString(f.UniqueName)
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)
right := expr.Children[1]
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 {
return nil

View File

@ -14,26 +14,14 @@ type Function struct {
Package string
Name string
UniqueName string
All *Environment
File *fs.File
Body token.List
Input []*Parameter
Output []*Parameter
OutputTypes []types.Type
Functions map[string]*Function
Structs map[string]*types.Struct
Constants map[string]*Constant
DLLs dll.List
Err error
deferred []func()
count counter
}
// 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
count count
}

View File

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

View File

@ -33,7 +33,7 @@ func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Re
return field.Type, nil
}
constant, isConst := f.Constants[f.Package+"."+leftText+"."+rightText]
constant, isConst := f.All.Constants[f.Package+"."+leftText+"."+rightText]
if isConst {
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)
function, exists := f.Functions[uniqueName]
function, exists := f.All.Functions[uniqueName]
if exists {
f.File.Imports[leftText].Used = true

View File

@ -13,7 +13,7 @@ func (f *Function) ResolveTypes() error {
for i, param := range f.Input {
param.name = param.tokens[0].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 {
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 {
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 {
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
}