Implemented environment type
This commit is contained in:
parent
4caac57210
commit
91e01de3ad
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
@ -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
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)
|
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
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
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