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
}
allTypes[typ.UniqueName()] = typ
allTypes[typ.Name()] = typ
case file, ok := <-files:
if !ok {

View File

@ -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)

View File

@ -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)
}

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[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) {

View File

@ -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) {

View File

@ -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)

View File

@ -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
}

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)
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 {

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"
// 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
}

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
// 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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}