Improved type system
This commit is contained in:
@ -9,6 +9,10 @@ type Array struct {
|
||||
|
||||
// Name returns the type name.
|
||||
func (a *Array) Name() string {
|
||||
if a.Of == Any {
|
||||
return "[]Any"
|
||||
}
|
||||
|
||||
return "[]" + a.Of.Name()
|
||||
}
|
||||
|
||||
|
@ -10,25 +10,27 @@ func ByName(name string, pkg string, structs map[string]*Struct) Type {
|
||||
to := strings.TrimPrefix(name, "*")
|
||||
typ := ByName(to, pkg, structs)
|
||||
|
||||
if typ != nil {
|
||||
return &Pointer{To: typ}
|
||||
if typ == Any {
|
||||
return AnyPointer
|
||||
}
|
||||
|
||||
return nil
|
||||
return &Pointer{To: typ}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, "[]") {
|
||||
to := strings.TrimPrefix(name, "[]")
|
||||
typ := ByName(to, pkg, structs)
|
||||
|
||||
if typ != nil {
|
||||
return &Array{Of: typ}
|
||||
if typ == Any {
|
||||
return AnyArray
|
||||
}
|
||||
|
||||
return nil
|
||||
return &Array{Of: typ}
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "Any":
|
||||
return Any
|
||||
case "Int":
|
||||
return Int
|
||||
case "Int64":
|
||||
@ -45,8 +47,6 @@ func ByName(name string, pkg string, structs map[string]*Struct) Type {
|
||||
return Float64
|
||||
case "Float32":
|
||||
return Float32
|
||||
case "Pointer":
|
||||
return AnyPointer
|
||||
}
|
||||
|
||||
typ, exists := structs[pkg+"."+name]
|
||||
|
18
src/types/Common.go
Normal file
18
src/types/Common.go
Normal file
@ -0,0 +1,18 @@
|
||||
package types
|
||||
|
||||
var (
|
||||
Any = &Base{name: "Any", size: 0}
|
||||
AnyArray = &Array{Of: Any}
|
||||
AnyPointer = &Pointer{To: Any}
|
||||
Int64 = &Base{name: "Int64", size: 8}
|
||||
Int32 = &Base{name: "Int32", size: 4}
|
||||
Int16 = &Base{name: "Int16", size: 2}
|
||||
Int8 = &Base{name: "Int8", size: 1}
|
||||
Float64 = &Base{name: "Float64", size: 8}
|
||||
Float32 = &Base{name: "Float32", size: 4}
|
||||
)
|
||||
|
||||
var (
|
||||
Int = Int64
|
||||
Float = Float64
|
||||
)
|
@ -1,7 +0,0 @@
|
||||
package types
|
||||
|
||||
var (
|
||||
Float64 = &Base{name: "Float64", size: 8}
|
||||
Float32 = &Base{name: "Float32", size: 4}
|
||||
Float = Float64
|
||||
)
|
@ -1,9 +0,0 @@
|
||||
package types
|
||||
|
||||
var (
|
||||
Int64 = &Base{name: "Int64", size: 8}
|
||||
Int32 = &Base{name: "Int32", size: 4}
|
||||
Int16 = &Base{name: "Int16", size: 2}
|
||||
Int8 = &Base{name: "Int8", size: 1}
|
||||
Int = Int64
|
||||
)
|
@ -2,30 +2,26 @@ package types
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
if a == b {
|
||||
if a == b || b == Any || a == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
aPointer, aIsPointer := a.(*Pointer)
|
||||
bPointer, bIsPointer := b.(*Pointer)
|
||||
|
||||
if aIsPointer && bIsPointer && (bPointer.To == nil || aPointer.To == bPointer.To) {
|
||||
if aIsPointer && bIsPointer && (bPointer.To == Any || aPointer.To == bPointer.To) {
|
||||
return true
|
||||
}
|
||||
|
||||
aArray, aIsArray := a.(*Array)
|
||||
|
||||
if aIsArray && bIsPointer && (bPointer.To == nil || aArray.Of == bPointer.To) {
|
||||
if aIsArray && bIsPointer && (bPointer.To == Any || aArray.Of == bPointer.To) {
|
||||
return true
|
||||
}
|
||||
|
||||
bArray, bIsArray := b.(*Array)
|
||||
|
||||
if aIsArray && bIsArray && aArray.Of == bArray.Of {
|
||||
if aIsArray && bIsArray && (bArray.Of == Any || aArray.Of == bArray.Of) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
package types
|
||||
|
||||
var AnyPointer = &Pointer{To: nil}
|
||||
|
||||
// Pointer is the address of an object.
|
||||
type Pointer struct {
|
||||
To Type
|
||||
@ -10,7 +8,7 @@ type Pointer struct {
|
||||
// Name returns the type name.
|
||||
func (p *Pointer) Name() string {
|
||||
if p.To == nil {
|
||||
return "Pointer"
|
||||
return "*Any"
|
||||
}
|
||||
|
||||
return "*" + p.To.Name()
|
||||
|
@ -9,7 +9,8 @@ import (
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
assert.Equal(t, types.Int.Name(), "Int64")
|
||||
assert.Equal(t, types.AnyPointer.Name(), "Pointer")
|
||||
assert.Equal(t, types.AnyArray.Name(), "[]Any")
|
||||
assert.Equal(t, types.AnyPointer.Name(), "*Any")
|
||||
assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "*Int64")
|
||||
assert.Equal(t, (&types.Array{Of: types.Int}).Name(), "[]Int64")
|
||||
assert.Equal(t, types.String.Name(), "[]Int8")
|
||||
@ -21,6 +22,7 @@ func TestSize(t *testing.T) {
|
||||
assert.Equal(t, types.Int16.Size(), 2)
|
||||
assert.Equal(t, types.Int32.Size(), 4)
|
||||
assert.Equal(t, types.Int64.Size(), 8)
|
||||
assert.Equal(t, types.AnyArray.Size(), 8)
|
||||
assert.Equal(t, types.AnyPointer.Size(), 8)
|
||||
assert.Equal(t, types.String.Size(), 8)
|
||||
assert.Equal(t, (&types.Pointer{To: types.Int}).Size(), 8)
|
||||
@ -39,9 +41,12 @@ func TestStruct(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
assert.True(t, types.Is(types.Int, types.Any))
|
||||
assert.True(t, types.Is(types.Int, types.Int))
|
||||
assert.True(t, types.Is(types.AnyPointer, types.AnyPointer))
|
||||
assert.True(t, types.Is(&types.Array{Of: types.Int}, types.AnyArray))
|
||||
assert.False(t, types.Is(types.Int, types.Float))
|
||||
assert.False(t, types.Is(types.Any, types.Int))
|
||||
assert.False(t, types.Is(&types.Pointer{To: types.Int}, &types.Pointer{To: types.Float}))
|
||||
}
|
||||
|
||||
@ -55,5 +60,9 @@ func TestSpecialCases(t *testing.T) {
|
||||
// A pointer pointing to a known type fulfills the requirement of a pointer to anything.
|
||||
assert.True(t, types.Is(&types.Pointer{To: types.Int}, types.AnyPointer))
|
||||
assert.True(t, types.Is(&types.Pointer{To: types.Float}, types.AnyPointer))
|
||||
|
||||
// Case #3:
|
||||
// Arrays are also just pointers.
|
||||
assert.True(t, types.Is(&types.Array{Of: types.Int}, types.AnyPointer))
|
||||
assert.True(t, types.Is(&types.Array{Of: types.Float}, types.AnyPointer))
|
||||
}
|
||||
|
Reference in New Issue
Block a user