Simplified type system

This commit is contained in:
Eduard Urbach 2025-02-04 23:58:01 +01:00
parent bde68d4d64
commit 8421a21c9a
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
16 changed files with 70 additions and 55 deletions

View File

@ -34,7 +34,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-c
continue continue
} }
allTypes[typ.UniqueName()] = typ allTypes[typ.Name()] = typ
case file, ok := <-files: case file, ok := <-files:
if !ok { if !ok {

View File

@ -27,14 +27,14 @@ func (f *Function) CompileAssignField(node *ast.Assign) error {
field := structure.FieldByName(fieldName) field := structure.FieldByName(fieldName)
if field == nil { if field == nil {
return errors.New(&errors.UnknownStructField{StructName: structure.Name, FieldName: fieldName}, f.File, destination.Children[1].Token.Position) return errors.New(&errors.UnknownStructField{StructName: structure.Name(), FieldName: fieldName}, f.File, destination.Children[1].Token.Position)
} }
memory := asm.Memory{ memory := asm.Memory{
Base: variable.Register, Base: variable.Register,
Offset: field.Offset, Offset: byte(field.Offset),
OffsetRegister: math.MaxUint8, OffsetRegister: math.MaxUint8,
Length: field.Type.TotalSize(), Length: byte(field.Type.Size()),
} }
_, err := f.ExpressionToMemory(value, memory) _, err := f.ExpressionToMemory(value, memory)

View File

@ -92,10 +92,10 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
return nil, err return nil, err
} }
if !types.Check(typ, fn.Parameters[i].Type) { if !types.Is(typ, fn.Parameters[i].Type) {
return nil, errors.New(&errors.TypeMismatch{ return nil, errors.New(&errors.TypeMismatch{
Encountered: typ.UniqueName(), Encountered: typ.Name(),
Expected: fn.Parameters[i].Type.UniqueName(), Expected: fn.Parameters[i].Type.Name(),
ParameterName: fn.Parameters[i].Name, ParameterName: fn.Parameters[i].Name,
}, f.File, parameters[i].Token.Position) }, f.File, parameters[i].Token.Position)
} }

View File

@ -15,7 +15,7 @@ func (f *Function) CompileDelete(root *expression.Expression) error {
f.SaveRegister(f.CPU.Input[0]) f.SaveRegister(f.CPU.Input[0])
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], int(variable.Type.(*types.Pointer).To.TotalSize())) f.RegisterNumber(asm.MOVE, f.CPU.Input[1], int(variable.Type.(*types.Pointer).To.Size()))
for _, register := range f.CPU.General { for _, register := range f.CPU.General {
if f.RegisterIsUsed(register) { if f.RegisterIsUsed(register) {

View File

@ -11,7 +11,7 @@ func (f *Function) CompileNew(root *expression.Expression) error {
structName := parameters[0].Token.Text(f.File.Bytes) structName := parameters[0].Token.Text(f.File.Bytes)
typ := f.Types[structName] typ := f.Types[structName]
f.SaveRegister(f.CPU.Input[0]) f.SaveRegister(f.CPU.Input[0])
f.RegisterNumber(asm.MOVE, f.CPU.Input[0], int(typ.TotalSize())) f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size())
for _, register := range f.CPU.General { for _, register := range f.CPU.General {
if f.RegisterIsUsed(register) { if f.RegisterIsUsed(register) {

View File

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

View File

@ -51,7 +51,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
right := node.Children[1] right := node.Children[1]
name = right.Token.Text(f.File.Bytes) name = right.Token.Text(f.File.Bytes)
field := variable.Type.(*types.Pointer).To.(*types.Struct).FieldByName(name) field := variable.Type.(*types.Pointer).To.(*types.Struct).FieldByName(name)
f.MemoryRegister(asm.LOAD, asm.Memory{Base: variable.Register, Offset: field.Offset, Length: field.Type.TotalSize()}, register) f.MemoryRegister(asm.LOAD, asm.Memory{Base: variable.Register, Offset: byte(field.Offset), Length: byte(field.Type.Size())}, register)
return field.Type, nil return field.Type, nil
} }

View File

@ -16,10 +16,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)
structure := types.NewStruct(structName)
structure := &types.Struct{
Name: structName,
}
i++ i++
@ -39,14 +36,12 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro
fieldType := types.Parse(fieldTypeName) fieldType := types.Parse(fieldTypeName)
i++ i++
structure.Fields = append(structure.Fields, &types.Field{ structure.AddField(&types.Field{
Type: fieldType, Type: fieldType,
Name: fieldName, Name: fieldName,
Position: token.Position(fieldPosition), Position: token.Position(fieldPosition),
Offset: structure.Size, Offset: structure.Size(),
}) })
structure.Size += fieldType.TotalSize()
} }
if tokens[i].Kind == token.BlockEnd { if tokens[i].Kind == token.BlockEnd {

View File

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

View File

@ -2,10 +2,10 @@ package types
import "git.akyoto.dev/cli/q/src/token" import "git.akyoto.dev/cli/q/src/token"
// Field is a field in a data structure. // Field is a memory region 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 int
} }

7
src/types/Float.go Normal file
View File

@ -0,0 +1,7 @@
package types
var (
Float64 = &Struct{name: "Float64", size: 8}
Float32 = &Struct{name: "Float32", size: 4}
Float = Float64
)

9
src/types/Int.go Normal file
View File

@ -0,0 +1,9 @@
package types
var (
Int64 = &Struct{name: "Int64", size: 8}
Int32 = &Struct{name: "Int32", size: 4}
Int16 = &Struct{name: "Int16", size: 2}
Int8 = &Struct{name: "Int8", size: 1}
Int = Int64
)

View File

@ -1,7 +1,7 @@
package types package types
// Check returns true if the encountered type `a` can be converted into the expected type `b`. // Is returns true if the encountered type `a` can be converted into the expected type `b`.
func Check(a Type, b Type) bool { func Is(a Type, b Type) bool {
if a == nil { if a == nil {
return true return true
} }

View File

@ -1,17 +1,22 @@
package types package types
var PointerAny = &Pointer{To: nil}
// Pointer is the address of an object.
type Pointer struct { type Pointer struct {
To Type To Type
} }
func (p *Pointer) UniqueName() string { // Name returns the type name.
func (p *Pointer) Name() string {
if p.To == nil { if p.To == nil {
return "Pointer" return "Pointer"
} }
return "Pointer:" + p.To.UniqueName() return "Pointer:" + p.To.Name()
} }
func (p *Pointer) TotalSize() uint8 { // Size returns the total size in bytes.
func (p *Pointer) Size() int {
return 8 return 8
} }

View File

@ -1,22 +1,26 @@
package types package types
// Struct is a structure in memory whose regions are addressable with fields. // Struct is a structure in memory whose regions are addressable with named fields.
type Struct struct { type Struct struct {
Name string name string
Fields []*Field fields []*Field
Size uint8 size int
} }
func (s *Struct) UniqueName() string { // NewStruct creates a new struct.
return s.Name func NewStruct(name string) *Struct {
return &Struct{name: name}
} }
func (s *Struct) TotalSize() uint8 { // AddField adds a new field to the end of the struct.
return s.Size func (s *Struct) AddField(field *Field) {
s.fields = append(s.fields, field)
s.size += field.Type.Size()
} }
// FieldByName returns the field with the given name if it exists.
func (s *Struct) FieldByName(name string) *Field { func (s *Struct) FieldByName(name string) *Field {
for _, field := range s.Fields { for _, field := range s.fields {
if field.Name == name { if field.Name == name {
return field return field
} }
@ -24,3 +28,13 @@ func (s *Struct) FieldByName(name string) *Field {
return nil return nil
} }
// Name returns the name of the struct.
func (s *Struct) Name() string {
return s.name
}
// Size returns the total size in bytes.
func (s *Struct) Size() int {
return s.size
}

View File

@ -1,6 +1,7 @@
package types package types
// Type is the generic interface for different data types.
type Type interface { type Type interface {
UniqueName() string Name() string
TotalSize() uint8 Size() int
} }