From 8421a21c9ad280133ccb1039b1d00dba7a796714 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Tue, 4 Feb 2025 23:58:01 +0100 Subject: [PATCH] Simplified type system --- src/compiler/Compile.go | 2 +- src/core/CompileAssignField.go | 6 +++--- src/core/CompileCall.go | 6 +++--- src/core/CompileDelete.go | 2 +- src/core/CompileNew.go | 2 +- src/core/CompileReturn.go | 6 +++--- src/core/ExpressionToRegister.go | 2 +- src/scanner/scanStruct.go | 11 +++-------- src/types/Base.go | 16 ---------------- src/types/Field.go | 4 ++-- src/types/Float.go | 7 +++++++ src/types/Int.go | 9 +++++++++ src/types/{Check.go => Is.go} | 4 ++-- src/types/Pointer.go | 11 ++++++++--- src/types/Struct.go | 32 +++++++++++++++++++++++--------- src/types/Type.go | 5 +++-- 16 files changed, 70 insertions(+), 55 deletions(-) delete mode 100644 src/types/Base.go create mode 100644 src/types/Float.go create mode 100644 src/types/Int.go rename src/types/{Check.go => Is.go} (68%) diff --git a/src/compiler/Compile.go b/src/compiler/Compile.go index 28ffb2e..23960a1 100644 --- a/src/compiler/Compile.go +++ b/src/compiler/Compile.go @@ -34,7 +34,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-c continue } - allTypes[typ.UniqueName()] = typ + allTypes[typ.Name()] = typ case file, ok := <-files: if !ok { diff --git a/src/core/CompileAssignField.go b/src/core/CompileAssignField.go index 26d462f..852ae2d 100644 --- a/src/core/CompileAssignField.go +++ b/src/core/CompileAssignField.go @@ -27,14 +27,14 @@ func (f *Function) CompileAssignField(node *ast.Assign) error { field := structure.FieldByName(fieldName) 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{ Base: variable.Register, - Offset: field.Offset, + Offset: byte(field.Offset), OffsetRegister: math.MaxUint8, - Length: field.Type.TotalSize(), + Length: byte(field.Type.Size()), } _, err := f.ExpressionToMemory(value, memory) diff --git a/src/core/CompileCall.go b/src/core/CompileCall.go index f476d94..d65baec 100644 --- a/src/core/CompileCall.go +++ b/src/core/CompileCall.go @@ -92,10 +92,10 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) { 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{ - Encountered: typ.UniqueName(), - Expected: fn.Parameters[i].Type.UniqueName(), + Encountered: typ.Name(), + Expected: fn.Parameters[i].Type.Name(), ParameterName: fn.Parameters[i].Name, }, f.File, parameters[i].Token.Position) } diff --git a/src/core/CompileDelete.go b/src/core/CompileDelete.go index 1e1b475..a8f46bd 100644 --- a/src/core/CompileDelete.go +++ b/src/core/CompileDelete.go @@ -15,7 +15,7 @@ func (f *Function) CompileDelete(root *expression.Expression) error { 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())) + f.RegisterNumber(asm.MOVE, f.CPU.Input[1], int(variable.Type.(*types.Pointer).To.Size())) for _, register := range f.CPU.General { if f.RegisterIsUsed(register) { diff --git a/src/core/CompileNew.go b/src/core/CompileNew.go index 04c6eb1..cdbf76d 100644 --- a/src/core/CompileNew.go +++ b/src/core/CompileNew.go @@ -11,7 +11,7 @@ func (f *Function) CompileNew(root *expression.Expression) error { 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())) + f.RegisterNumber(asm.MOVE, f.CPU.Input[0], typ.Size()) for _, register := range f.CPU.General { if f.RegisterIsUsed(register) { diff --git a/src/core/CompileReturn.go b/src/core/CompileReturn.go index 023da02..9b84b58 100644 --- a/src/core/CompileReturn.go +++ b/src/core/CompileReturn.go @@ -25,10 +25,10 @@ func (f *Function) CompileReturn(node *ast.Return) error { return err } - if !types.Check(typ, f.ReturnTypes[i]) { + if !types.Is(typ, f.ReturnTypes[i]) { return errors.New(&errors.TypeMismatch{ - Encountered: typ.UniqueName(), - Expected: f.ReturnTypes[i].UniqueName(), + Encountered: typ.Name(), + Expected: f.ReturnTypes[i].Name(), ParameterName: "", IsReturn: true, }, f.File, node.Values[i].Token.Position) diff --git a/src/core/ExpressionToRegister.go b/src/core/ExpressionToRegister.go index 684ad38..aa6ad9b 100644 --- a/src/core/ExpressionToRegister.go +++ b/src/core/ExpressionToRegister.go @@ -51,7 +51,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp right := node.Children[1] name = right.Token.Text(f.File.Bytes) 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 } diff --git a/src/scanner/scanStruct.go b/src/scanner/scanStruct.go index 40ecf36..e99165f 100644 --- a/src/scanner/scanStruct.go +++ b/src/scanner/scanStruct.go @@ -16,10 +16,7 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro } structName := tokens[i].Text(file.Bytes) - - structure := &types.Struct{ - Name: structName, - } + structure := types.NewStruct(structName) i++ @@ -39,14 +36,12 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro fieldType := types.Parse(fieldTypeName) i++ - structure.Fields = append(structure.Fields, &types.Field{ + structure.AddField(&types.Field{ Type: fieldType, Name: fieldName, Position: token.Position(fieldPosition), - Offset: structure.Size, + Offset: structure.Size(), }) - - structure.Size += fieldType.TotalSize() } if tokens[i].Kind == token.BlockEnd { diff --git a/src/types/Base.go b/src/types/Base.go deleted file mode 100644 index 5f3d27b..0000000 --- a/src/types/Base.go +++ /dev/null @@ -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 -) diff --git a/src/types/Field.go b/src/types/Field.go index 6e155ff..e486878 100644 --- a/src/types/Field.go +++ b/src/types/Field.go @@ -2,10 +2,10 @@ package types 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 Type Name string Position token.Position - Offset uint8 + Offset int } diff --git a/src/types/Float.go b/src/types/Float.go new file mode 100644 index 0000000..1fedd30 --- /dev/null +++ b/src/types/Float.go @@ -0,0 +1,7 @@ +package types + +var ( + Float64 = &Struct{name: "Float64", size: 8} + Float32 = &Struct{name: "Float32", size: 4} + Float = Float64 +) diff --git a/src/types/Int.go b/src/types/Int.go new file mode 100644 index 0000000..73fa22c --- /dev/null +++ b/src/types/Int.go @@ -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 +) diff --git a/src/types/Check.go b/src/types/Is.go similarity index 68% rename from src/types/Check.go rename to src/types/Is.go index fe1eb20..9adbac5 100644 --- a/src/types/Check.go +++ b/src/types/Is.go @@ -1,7 +1,7 @@ package types -// Check returns true if the encountered type `a` can be converted into the expected type `b`. -func Check(a Type, b Type) bool { +// Is returns true if the encountered type `a` can be converted into the expected type `b`. +func Is(a Type, b Type) bool { if a == nil { return true } diff --git a/src/types/Pointer.go b/src/types/Pointer.go index ccc92e7..06a712e 100644 --- a/src/types/Pointer.go +++ b/src/types/Pointer.go @@ -1,17 +1,22 @@ package types +var PointerAny = &Pointer{To: nil} + +// Pointer is the address of an object. type Pointer struct { To Type } -func (p *Pointer) UniqueName() string { +// Name returns the type name. +func (p *Pointer) Name() string { if p.To == nil { 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 } diff --git a/src/types/Struct.go b/src/types/Struct.go index d24bdb5..1e80517 100644 --- a/src/types/Struct.go +++ b/src/types/Struct.go @@ -1,22 +1,26 @@ 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 { - Name string - Fields []*Field - Size uint8 + name string + fields []*Field + size int } -func (s *Struct) UniqueName() string { - return s.Name +// NewStruct creates a new struct. +func NewStruct(name string) *Struct { + return &Struct{name: name} } -func (s *Struct) TotalSize() uint8 { - return s.Size +// AddField adds a new field to the end of the struct. +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 { - for _, field := range s.Fields { + for _, field := range s.fields { if field.Name == name { return field } @@ -24,3 +28,13 @@ func (s *Struct) FieldByName(name string) *Field { 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 +} diff --git a/src/types/Type.go b/src/types/Type.go index d548867..ef55b60 100644 --- a/src/types/Type.go +++ b/src/types/Type.go @@ -1,6 +1,7 @@ package types +// Type is the generic interface for different data types. type Type interface { - UniqueName() string - TotalSize() uint8 + Name() string + Size() int }