Implemented environment type
This commit is contained in:
parent
4caac57210
commit
91e01de3ad
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
14
src/core/Environment.go
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
13
src/core/count.go
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user