Added basic equality checks to types

This commit is contained in:
Sasha Koshka 2023-10-19 21:53:19 -04:00
parent 84f76f8ba4
commit 5d4977828e
2 changed files with 89 additions and 7 deletions

View File

@ -30,6 +30,20 @@ func (this *Signature) String () string {
}
return out
}
func (this *Signature) Equals (ty Type) bool {
real, ok := ty.(*Signature)
if !ok ||
len(real.Arguments) != len(this.Arguments) ||
!real.Return.Equals(this.Return) ||
real.Name != this.Name { return false }
for index, argument := range this.Arguments {
if !argument.Type.Equals(real.Arguments[index].Type) {
return false
}
}
return true
}
// Member is a syntactical construct that is used to list members in struct
// literals.

View File

@ -5,17 +5,20 @@ import "github.com/alecthomas/participle/v2/lexer"
// Type is any type notation.
type Type interface {
// Equals reports whether this type is equivalent to another type.
Equals (ty Type) bool
ty ()
}
type void struct { }
func (void) ty(){}
// Void returns the absence of a type. It can be compared to a Type to find out
// if it is filled in, but has no type.
func Void () Type {
return void { }
// Void represents the absence of a type.
type Void struct { }
func (*Void) ty(){}
func (*Void) Equals (ty Type) bool {
_, equals := ty.(*Void)
return equals
}
func (*Void) String () string { return "Void" }
// TypeNamed refers to a user-defined or built in named type.
type TypeNamed struct {
@ -25,6 +28,10 @@ type TypeNamed struct {
}
func (*TypeNamed) ty(){}
func (this *TypeNamed) String () string { return this.Name }
func (this *TypeNamed) Equals (ty Type) bool {
real, ok := ty.(*TypeNamed)
return ok && real.Name == this.Name
}
// TypePointer is a pointer to another type.
type TypePointer struct {
@ -35,6 +42,10 @@ func (*TypePointer) ty(){}
func (this *TypePointer) String () string {
return fmt.Sprint("*", this.Referenced)
}
func (this *TypePointer) Equals (ty Type) bool {
real, ok := ty.(*TypePointer)
return ok && real.Referenced.Equals(this.Referenced)
}
// TypeSlice is a pointer to several values of a given type stored next to
// eachother. Its length is not built into its type and can be changed at
@ -47,6 +58,10 @@ func (*TypeSlice) ty(){}
func (this *TypeSlice) String () string {
return fmt.Sprint("*:", this.Element)
}
func (this *TypeSlice) Equals (ty Type) bool {
real, ok := ty.(*TypeSlice)
return ok && real.Element.Equals(this.Element)
}
// TypeArray is a group of values of a given type stored next to eachother. The
// length of an array is fixed and is part of its type. Arrays are passed by
@ -60,6 +75,12 @@ func (*TypeArray) ty(){}
func (this *TypeArray) String () string {
return fmt.Sprint(this.Length, ":", this.Element)
}
func (this *TypeArray) Equals (ty Type) bool {
real, ok := ty.(*TypeArray)
return ok &&
real.Length == this.Length &&
real.Element.Equals(this.Element)
}
// TypeStruct is a composite type that stores keyed values. The positions of the
// values within the struct are decided at compile time, based on the order they
@ -82,6 +103,17 @@ func (this *TypeStruct) String () string {
}
return out + ")"
}
func (this *TypeStruct) Equals (ty Type) bool {
real, ok := ty.(*TypeStruct)
if !ok || len(real.Members) != len(this.Members) { return false }
for index, member := range this.Members {
if !member.Type.Equals(real.Members[index].Type) {
return false
}
}
return true
}
// TypeInterface is a polymorphic pointer that allows any value of any type
// through, except it must have at least the methods defined within the
@ -106,6 +138,17 @@ func (this *TypeInterface) String () string {
}
return out + ")"
}
func (this *TypeInterface) Equals (ty Type) bool {
real, ok := ty.(*TypeInterface)
if !ok || len(real.Behaviors) != len(this.Behaviors) { return false }
for index, behavior := range this.Behaviors {
if !behavior.Equals(real.Behaviors[index]) {
return false
}
}
return true
}
// TypeInt represents any signed or unsigned integer type.
type TypeInt struct {
@ -114,6 +157,13 @@ type TypeInt struct {
Signed bool
}
func (*TypeInt) ty(){}
func (this *TypeInt) String () string {
return fmt.Sprint("I", this.Width)
}
func (this *TypeInt) Equals (ty Type) bool {
real, ok := ty.(*TypeInt)
return ok && real.Width == this.Width && real.Signed == this.Signed
}
// TypeFloat represents any floating point type.
type TypeFloat struct {
@ -121,6 +171,13 @@ type TypeFloat struct {
Width int
}
func (*TypeFloat) ty(){}
func (this *TypeFloat) String () string {
return fmt.Sprint("F", this.Width)
}
func (this *TypeFloat) Equals (ty Type) bool {
real, ok := ty.(*TypeFloat)
return ok && real.Width == this.Width
}
// TypeWord represents an integer type of unspecified width. The optimal width
// is chosen based on the machine word size (32 on 32 bit systems, 64 on 64 bit
@ -130,3 +187,14 @@ type TypeWord struct {
Signed bool
}
func (*TypeWord) ty(){}
func (this *TypeWord) String () string {
if this.Signed {
return "Int"
} else {
return "UInt"
}
}
func (this *TypeWord) Equals (ty Type) bool {
real, ok := ty.(*TypeWord)
return ok && real.Signed == this.Signed
}