Implemented structs

This commit is contained in:
Eduard Urbach 2025-02-04 18:16:31 +01:00
parent 4609a814df
commit 03a3bd8f02
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
32 changed files with 267 additions and 63 deletions

11
examples/point/point.q Normal file
View File

@ -0,0 +1,11 @@
struct Point {
x Int
y Int
}
main() {
p := new(Point)
p.x = 4
p.y = 2
delete(p)
}

View File

@ -22,8 +22,8 @@ munmap(address Pointer, length Int) -> Int {
return syscall(11, address, length) return syscall(11, address, length)
} }
nanosleep(timespec Pointer) -> Int { nanosleep(duration Pointer) -> Int {
return syscall(35, timespec, 0) return syscall(35, duration, 0)
} }
clone(flags Int, stack Pointer) -> Int { clone(flags Int, stack Pointer) -> Int {

View File

@ -1,4 +1,3 @@
import mem
import sys import sys
sleep(nanoseconds Int) { sleep(nanoseconds Int) {
@ -8,10 +7,9 @@ sleep(nanoseconds Int) {
seconds, nanoseconds = nanoseconds / 1000000000 seconds, nanoseconds = nanoseconds / 1000000000
} }
timespec := mem.alloc(16) duration := new(timespec)
store(timespec, 8, seconds) duration.seconds = seconds
offset := timespec + 8 duration.nanoseconds = nanoseconds
store(offset, 8, nanoseconds) sys.nanosleep(duration)
sys.nanosleep(timespec) delete(duration)
mem.free(timespec, 16)
} }

View File

@ -2,6 +2,7 @@ package asm
import ( import (
"fmt" "fmt"
"math"
) )
// MemoryLabel operates with a memory address and a number. // MemoryLabel operates with a memory address and a number.
@ -12,6 +13,10 @@ type MemoryLabel struct {
// String returns a human readable version. // String returns a human readable version.
func (data *MemoryLabel) String() string { func (data *MemoryLabel) String() string {
if data.Address.OffsetRegister == math.MaxUint8 {
return fmt.Sprintf("%dB [%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.Offset, data.Label)
}
return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Label) return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Label)
} }

View File

@ -2,6 +2,7 @@ package asm
import ( import (
"fmt" "fmt"
"math"
) )
// MemoryNumber operates with a memory address and a number. // MemoryNumber operates with a memory address and a number.
@ -12,6 +13,10 @@ type MemoryNumber struct {
// String returns a human readable version. // String returns a human readable version.
func (data *MemoryNumber) String() string { func (data *MemoryNumber) String() string {
if data.Address.OffsetRegister == math.MaxUint8 {
return fmt.Sprintf("%dB [%s+%d], %d", data.Address.Length, data.Address.Base, data.Address.Offset, data.Number)
}
return fmt.Sprintf("%dB [%s+%s+%d], %d", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Number) return fmt.Sprintf("%dB [%s+%s+%d], %d", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Number)
} }

View File

@ -2,6 +2,7 @@ package asm
import ( import (
"fmt" "fmt"
"math"
"git.akyoto.dev/cli/q/src/cpu" "git.akyoto.dev/cli/q/src/cpu"
) )
@ -14,6 +15,10 @@ type MemoryRegister struct {
// String returns a human readable version. // String returns a human readable version.
func (data *MemoryRegister) String() string { func (data *MemoryRegister) String() string {
if data.Address.OffsetRegister == math.MaxUint8 {
return fmt.Sprintf("%dB [%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.Offset, data.Register)
}
return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Register) return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Register)
} }

View File

@ -10,11 +10,11 @@ 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(files <-chan *fs.File, functions <-chan *core.Function, structs <-chan *types.Type, errs <-chan error) (Result, error) { func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-chan types.Type, errs <-chan error) (Result, error) {
result := Result{} result := Result{}
allFiles := make([]*fs.File, 0, 8) allFiles := make([]*fs.File, 0, 8)
allFunctions := map[string]*core.Function{} allFunctions := map[string]*core.Function{}
allTypes := map[string]*types.Type{} allTypes := map[string]types.Type{}
for functions != nil || files != nil || errs != nil { for functions != nil || files != nil || errs != nil {
select { select {
@ -25,6 +25,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-c
} }
function.Functions = allFunctions function.Functions = allFunctions
function.Types = allTypes
allFunctions[function.UniqueName] = function allFunctions[function.UniqueName] = function
case typ, ok := <-structs: case typ, ok := <-structs:
@ -33,7 +34,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-c
continue continue
} }
allTypes[typ.Name] = typ allTypes[typ.UniqueName()] = typ
case file, ok := <-files: case file, ok := <-files:
if !ok { if !ok {

View File

@ -26,6 +26,10 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
return f.Execute(operator, variable.Register, right) return f.Execute(operator, variable.Register, right)
} }
if left.Token.Kind == token.Period {
return f.CompileAssignField(node)
}
if left.Token.Kind == token.Array { if left.Token.Kind == token.Array {
return f.CompileAssignArray(node) return f.CompileAssignArray(node)
} }

View File

@ -0,0 +1,44 @@
package core
import (
"math"
"git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/ast"
"git.akyoto.dev/cli/q/src/errors"
"git.akyoto.dev/cli/q/src/types"
)
// CompileAssignField compiles a memory write to a struct field.
func (f *Function) CompileAssignField(node *ast.Assign) error {
destination := node.Expression.Children[0]
value := node.Expression.Children[1]
name := destination.Children[0].Token.Text(f.File.Bytes)
fieldName := destination.Children[1].Token.Text(f.File.Bytes)
variable := f.VariableByName(name)
if variable == nil {
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, destination.Children[0].Token.Position)
}
defer f.UseVariable(variable)
pointer := variable.Type.(*types.Pointer)
structure := pointer.To.(*types.Struct)
for _, field := range structure.Fields {
if field.Name == fieldName {
memory := asm.Memory{
Base: variable.Register,
Offset: field.Offset,
OffsetRegister: math.MaxUint8,
Length: field.Type.TotalSize(),
}
_, err := f.ExpressionToMemory(value, memory)
return err
}
}
// TODO: unknown field error
return nil
}

View File

@ -26,11 +26,20 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
if nameNode.IsLeaf() { if nameNode.IsLeaf() {
name = nameNode.Token.Text(f.File.Bytes) name = nameNode.Token.Text(f.File.Bytes)
if name == "syscall" { switch name {
case "syscall":
return nil, f.CompileSyscall(root) return nil, f.CompileSyscall(root)
} case "new":
return &Function{
if name == "store" { ReturnTypes: []types.Type{
&types.Pointer{
To: f.Types[root.Children[1].Token.Text(f.File.Bytes)],
},
},
}, f.CompileNew(root)
case "delete":
return nil, f.CompileDelete(root)
case "store":
return nil, f.CompileMemoryStore(root) return nil, f.CompileMemoryStore(root)
} }
} else { } else {
@ -85,8 +94,8 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
if !types.Check(typ, fn.Parameters[i].Type) { if !types.Check(typ, fn.Parameters[i].Type) {
return nil, errors.New(&errors.TypeMismatch{ return nil, errors.New(&errors.TypeMismatch{
Encountered: typ.Name, Encountered: typ.UniqueName(),
Expected: fn.Parameters[i].Type.Name, Expected: fn.Parameters[i].Type.UniqueName(),
ParameterName: fn.Parameters[i].Name, ParameterName: fn.Parameters[i].Name,
}, f.File, parameters[i].Token.Position) }, f.File, parameters[i].Token.Position)
} }

37
src/core/CompileDelete.go Normal file
View File

@ -0,0 +1,37 @@
package core
import (
"git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/expression"
"git.akyoto.dev/cli/q/src/types"
)
// CompileDelete compiles a `delete` function call which deallocates a struct.
func (f *Function) CompileDelete(root *expression.Expression) error {
parameters := root.Children[1:]
variableName := parameters[0].Token.Text(f.File.Bytes)
variable := f.VariableByName(variableName)
defer f.UseVariable(variable)
f.SaveRegister(f.CPU.Input[0])
f.SaveRegister(f.CPU.Input[1])
f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Register)
f.RegisterNumber(asm.MOVE, f.CPU.Input[1], int(variable.Type.(*types.Pointer).To.TotalSize()))
for _, register := range f.CPU.General {
if f.RegisterIsUsed(register) {
f.Register(asm.PUSH, register)
}
}
f.Call("mem.free")
for i := len(f.CPU.General) - 1; i >= 0; i-- {
register := f.CPU.General[i]
if f.RegisterIsUsed(register) {
f.Register(asm.POP, register)
}
}
return nil
}

View File

@ -8,7 +8,7 @@ import (
"git.akyoto.dev/cli/q/src/expression" "git.akyoto.dev/cli/q/src/expression"
) )
// CompileMemoryStore ... // CompileMemoryStore compiles a variable-width store to memory.
func (f *Function) CompileMemoryStore(root *expression.Expression) error { func (f *Function) CompileMemoryStore(root *expression.Expression) error {
parameters := root.Children[1:] parameters := root.Children[1:]
name := parameters[0].Token.Text(f.File.Bytes) name := parameters[0].Token.Text(f.File.Bytes)

33
src/core/CompileNew.go Normal file
View File

@ -0,0 +1,33 @@
package core
import (
"git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/expression"
)
// CompileNew compiles a `new` function call which allocates a struct.
func (f *Function) CompileNew(root *expression.Expression) error {
parameters := root.Children[1:]
structName := parameters[0].Token.Text(f.File.Bytes)
typ := f.Types[structName]
f.SaveRegister(f.CPU.Input[0])
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], int(typ.TotalSize()))
for _, register := range f.CPU.General {
if f.RegisterIsUsed(register) {
f.Register(asm.PUSH, register)
}
}
f.Call("mem.alloc")
for i := len(f.CPU.General) - 1; i >= 0; i-- {
register := f.CPU.General[i]
if f.RegisterIsUsed(register) {
f.Register(asm.POP, register)
}
}
return nil
}

View File

@ -27,8 +27,8 @@ func (f *Function) CompileReturn(node *ast.Return) error {
if !types.Check(typ, f.ReturnTypes[i]) { if !types.Check(typ, f.ReturnTypes[i]) {
return errors.New(&errors.TypeMismatch{ return errors.New(&errors.TypeMismatch{
Encountered: typ.Name, Encountered: typ.UniqueName(),
Expected: f.ReturnTypes[i].Name, Expected: f.ReturnTypes[i].UniqueName(),
ParameterName: "", ParameterName: "",
IsReturn: true, IsReturn: true,
}, f.File, node.Values[i].Token.Position) }, f.File, node.Values[i].Token.Position)

View File

@ -8,7 +8,7 @@ import (
) )
// Evaluate evaluates an expression and returns a register that contains the value of the expression. // Evaluate evaluates an expression and returns a register that contains the value of the expression.
func (f *Function) Evaluate(expr *expression.Expression) (*types.Type, cpu.Register, bool, error) { func (f *Function) Evaluate(expr *expression.Expression) (types.Type, cpu.Register, bool, error) {
if expr.Token.Kind == token.Identifier { if expr.Token.Kind == token.Identifier {
name := expr.Token.Text(f.File.Bytes) name := expr.Token.Text(f.File.Bytes)
variable := f.VariableByName(name) variable := f.VariableByName(name)

View File

@ -10,21 +10,21 @@ import (
) )
// ExpressionToMemory puts the result of an expression into the specified memory address. // ExpressionToMemory puts the result of an expression into the specified memory address.
func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Memory) (*types.Type, error) { func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Memory) (types.Type, error) {
if node.IsLeaf() { if node.IsLeaf() {
if node.Token.Kind == token.Identifier { if node.Token.Kind == token.Identifier {
name := node.Token.Text(f.File.Bytes) name := node.Token.Text(f.File.Bytes)
variable, function := f.Identifier(name) variable, function := f.Identifier(name)
if variable != nil { if variable != nil {
f.UseVariable(variable)
f.MemoryRegister(asm.STORE, memory, variable.Register) f.MemoryRegister(asm.STORE, memory, variable.Register)
return types.Pointer, nil f.UseVariable(variable)
return types.PointerAny, nil
} }
if function != nil { if function != nil {
f.MemoryLabel(asm.STORE, memory, function.UniqueName) f.MemoryLabel(asm.STORE, memory, function.UniqueName)
return types.Pointer, nil return types.PointerAny, nil
} }
return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, node.Token.Position) return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, node.Token.Position)
@ -39,7 +39,7 @@ func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Me
size := byte(sizeof.Signed(int64(number))) size := byte(sizeof.Signed(int64(number)))
if size != memory.Length { if size > memory.Length {
return nil, errors.New(&errors.NumberExceedsBounds{Number: number, ExpectedSize: memory.Length, Size: size}, f.File, node.Token.Position) return nil, errors.New(&errors.NumberExceedsBounds{Number: number, ExpectedSize: memory.Length, Size: size}, f.File, node.Token.Position)
} }

View File

@ -11,7 +11,7 @@ import (
) )
// ExpressionToRegister puts the result of an expression into the specified register. // ExpressionToRegister puts the result of an expression into the specified register.
func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (*types.Type, error) { func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) {
f.SaveRegister(register) f.SaveRegister(register)
if node.IsFolded { if node.IsFolded {
@ -72,7 +72,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
return nil, err return nil, err
} }
if typ == types.Pointer && right.Token.Kind == token.Identifier && f.VariableByName(right.Token.Text(f.File.Bytes)).Type == types.Pointer { if typ == types.PointerAny && right.Token.Kind == token.Identifier && f.VariableByName(right.Token.Text(f.File.Bytes)).Type == types.PointerAny {
typ = types.Int typ = types.Int
} }

View File

@ -18,8 +18,9 @@ type Function struct {
File *fs.File File *fs.File
Body token.List Body token.List
Parameters []*scope.Variable Parameters []*scope.Variable
ReturnTypes []*types.Type ReturnTypes []types.Type
Functions map[string]*Function Functions map[string]*Function
Types map[string]types.Type
DLLs dll.List DLLs dll.List
Err error Err error
deferred []func() deferred []func()

View File

@ -10,7 +10,7 @@ import (
// TokenToRegister moves a token into a register. // TokenToRegister moves a token into a register.
// It only works with identifiers, numbers and strings. // It only works with identifiers, numbers and strings.
func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (*types.Type, error) { func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (types.Type, error) {
switch t.Kind { switch t.Kind {
case token.Identifier: case token.Identifier:
name := t.Text(f.File.Bytes) name := t.Text(f.File.Bytes)
@ -26,7 +26,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (*types
if function != nil { if function != nil {
f.SaveRegister(register) f.SaveRegister(register)
f.RegisterLabel(asm.MOVE, register, function.UniqueName) f.RegisterLabel(asm.MOVE, register, function.UniqueName)
return types.Pointer, nil return types.PointerAny, nil
} }
return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position) return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
@ -48,7 +48,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (*types
label := f.AddBytes(data) label := f.AddBytes(data)
f.SaveRegister(register) f.SaveRegister(register)
f.RegisterLabel(asm.MOVE, register, label) f.RegisterLabel(asm.MOVE, register, label)
return types.Pointer, nil return types.PointerAny, nil
default: default:
return nil, errors.New(errors.InvalidExpression, f.File, t.Position) return nil, errors.New(errors.InvalidExpression, f.File, t.Position)

View File

@ -1,20 +1,25 @@
package scanner package scanner
import ( import (
"path/filepath"
"git.akyoto.dev/cli/q/src/config"
"git.akyoto.dev/cli/q/src/core" "git.akyoto.dev/cli/q/src/core"
"git.akyoto.dev/cli/q/src/fs" "git.akyoto.dev/cli/q/src/fs"
"git.akyoto.dev/cli/q/src/types" "git.akyoto.dev/cli/q/src/types"
) )
// Scan scans the list of files. // Scan scans the list of files.
func Scan(files []string) (<-chan *fs.File, <-chan *core.Function, <-chan *types.Type, <-chan error) { func Scan(files []string) (<-chan *fs.File, <-chan *core.Function, <-chan types.Type, <-chan error) {
scanner := Scanner{ scanner := Scanner{
files: make(chan *fs.File), files: make(chan *fs.File),
functions: make(chan *core.Function), functions: make(chan *core.Function),
types: make(chan *types.Type), types: make(chan types.Type),
errors: make(chan error), errors: make(chan error),
} }
scanner.queueDirectory(filepath.Join(config.Library, "mem"), "mem")
go func() { go func() {
scanner.queue(files...) scanner.queue(files...)
scanner.group.Wait() scanner.group.Wait()

View File

@ -12,7 +12,7 @@ import (
type Scanner struct { type Scanner struct {
files chan *fs.File files chan *fs.File
functions chan *core.Function functions chan *core.Function
types chan *types.Type types chan types.Type
errors chan error errors chan error
queued sync.Map queued sync.Map
group sync.WaitGroup group sync.WaitGroup

View File

@ -17,7 +17,7 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro
structName := tokens[i].Text(file.Bytes) structName := tokens[i].Text(file.Bytes)
typ := &types.Type{ structure := &types.Struct{
Name: structName, Name: structName,
} }
@ -39,14 +39,14 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro
fieldType := types.Parse(fieldTypeName) fieldType := types.Parse(fieldTypeName)
i++ i++
typ.Fields = append(typ.Fields, &types.Field{ structure.Fields = append(structure.Fields, &types.Field{
Type: fieldType, Type: fieldType,
Name: fieldName, Name: fieldName,
Position: token.Position(fieldPosition), Position: token.Position(fieldPosition),
Offset: typ.Size, Offset: structure.Size,
}) })
typ.Size += fieldType.Size structure.Size += fieldType.TotalSize()
} }
if tokens[i].Kind == token.BlockEnd { if tokens[i].Kind == token.BlockEnd {
@ -61,6 +61,6 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro
return i, errors.New(errors.MissingBlockEnd, file, tokens[i].Position) return i, errors.New(errors.MissingBlockEnd, file, tokens[i].Position)
} }
s.types <- typ s.types <- structure
return i, nil return i, nil
} }

View File

@ -7,7 +7,7 @@ import (
// Variable represents a named register. // Variable represents a named register.
type Variable struct { type Variable struct {
Type *types.Type Type types.Type
Name string Name string
Alive uint8 Alive uint8
Register cpu.Register Register cpu.Register

View File

@ -1,13 +1,13 @@
package types package types
var ( var (
Float64 = &Type{Name: "Float64", Size: 8} Float64 = &Struct{Name: "Float64", Size: 8}
Float32 = &Type{Name: "Float32", Size: 4} Float32 = &Struct{Name: "Float32", Size: 4}
Int64 = &Type{Name: "Int64", Size: 8} Int64 = &Struct{Name: "Int64", Size: 8}
Int32 = &Type{Name: "Int32", Size: 4} Int32 = &Struct{Name: "Int32", Size: 4}
Int16 = &Type{Name: "Int16", Size: 2} Int16 = &Struct{Name: "Int16", Size: 2}
Int8 = &Type{Name: "Int8", Size: 1} Int8 = &Struct{Name: "Int8", Size: 1}
Pointer = &Type{Name: "Pointer", Size: 8} PointerAny = &Pointer{To: nil}
) )
var ( var (

View File

@ -1,6 +1,21 @@
package types package types
// Check returns true if the first type can be converted into the second type. // Check returns true if the encountered type `a` can be converted into the expected type `b`.
func Check(a *Type, b *Type) bool { func Check(a Type, b Type) bool {
return a == nil || a == b if a == nil {
return true
}
if a == b {
return true
}
aPointer, aIsPointer := a.(*Pointer)
bPointer, bIsPointer := b.(*Pointer)
if aIsPointer && bIsPointer && (bPointer.To == nil || aPointer.To == bPointer.To) {
return true
}
return false
} }

View File

@ -4,7 +4,7 @@ import "git.akyoto.dev/cli/q/src/token"
// Field is a field in a data structure. // Field is a field in a data structure.
type Field struct { type Field struct {
Type *Type Type Type
Name string Name string
Position token.Position Position token.Position
Offset uint8 Offset uint8

View File

@ -1,7 +1,7 @@
package types package types
// Parse creates a new type from a list of tokens. // Parse creates a new type from a list of tokens.
func Parse(name string) *Type { func Parse(name string) Type {
switch name { switch name {
case "Int": case "Int":
return Int return Int
@ -20,7 +20,7 @@ func Parse(name string) *Type {
case "Float32": case "Float32":
return Float32 return Float32
case "Pointer": case "Pointer":
return Pointer return PointerAny
default: default:
panic("Unknown type " + name) panic("Unknown type " + name)
} }

View File

@ -3,8 +3,8 @@ package types
import "git.akyoto.dev/cli/q/src/token" import "git.akyoto.dev/cli/q/src/token"
// ParseList generates a list of types from comma separated tokens. // ParseList generates a list of types from comma separated tokens.
func ParseList(tokens token.List, source []byte) []*Type { func ParseList(tokens token.List, source []byte) []Type {
var list []*Type var list []Type
tokens.Split(func(parameter token.List) error { tokens.Split(func(parameter token.List) error {
typ := Parse(parameter.Text(source)) typ := Parse(parameter.Text(source))

17
src/types/Pointer.go Normal file
View File

@ -0,0 +1,17 @@
package types
type Pointer struct {
To Type
}
func (p *Pointer) UniqueName() string {
if p.To == nil {
return "Pointer"
}
return "Pointer:" + p.To.UniqueName()
}
func (p *Pointer) TotalSize() uint8 {
return 8
}

16
src/types/Struct.go Normal file
View File

@ -0,0 +1,16 @@
package types
// Struct is a structure in memory whose regions are addressable with fields.
type Struct struct {
Name string
Fields []*Field
Size uint8
}
func (s *Struct) UniqueName() string {
return s.Name
}
func (s *Struct) TotalSize() uint8 {
return s.Size
}

View File

@ -1,8 +1,6 @@
package types package types
// Type represents a type in the type system. type Type interface {
type Type struct { UniqueName() string
Name string TotalSize() uint8
Fields []*Field
Size uint8
} }

View File

@ -25,7 +25,7 @@ var (
AllRegisters = []cpu.Register{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15} AllRegisters = []cpu.Register{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15}
SyscallInputRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9} SyscallInputRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11} SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11}
GeneralRegisters = []cpu.Register{RCX, RBX, RBP, R11, R12, R13, R14, R15} GeneralRegisters = []cpu.Register{RCX, RBX, R11, R12, R13, R14, R15, RBP}
InputRegisters = SyscallInputRegisters InputRegisters = SyscallInputRegisters
OutputRegisters = SyscallInputRegisters OutputRegisters = SyscallInputRegisters
WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9} WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9}