Simplified type system
This commit is contained in:
parent
bde68d4d64
commit
8421a21c9a
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
|
||||||
)
|
|
@ -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
7
src/types/Float.go
Normal 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
9
src/types/Int.go
Normal 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
|
||||||
|
)
|
@ -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
|
||||||
}
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user