This commit is contained in:
parent
ed6ae1d306
commit
714a722aaa
7 changed files with 189 additions and 1 deletions
16
src/types/Array.go
Normal file
16
src/types/Array.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
// Array is the address of an object.
|
||||||
|
type Array struct {
|
||||||
|
Of Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the type name.
|
||||||
|
func (a *Array) Name() string {
|
||||||
|
return "[]" + a.Of.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the total size in bytes.
|
||||||
|
func (a *Array) Size() int {
|
||||||
|
return 8
|
||||||
|
}
|
17
src/types/Base.go
Normal file
17
src/types/Base.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
// Base is used to describe basic types like integers and floats.
|
||||||
|
type Base struct {
|
||||||
|
name string
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the type.
|
||||||
|
func (s *Base) Name() string {
|
||||||
|
return s.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the total size in bytes.
|
||||||
|
func (s *Base) Size() int {
|
||||||
|
return s.size
|
||||||
|
}
|
27
src/types/Common.go
Normal file
27
src/types/Common.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
var (
|
||||||
|
Any = &Base{name: "any", size: 0}
|
||||||
|
AnyArray = &Array{Of: Any}
|
||||||
|
AnyInt = &Base{name: "int"}
|
||||||
|
AnyPointer = &Pointer{To: Any}
|
||||||
|
Bool = &Base{name: "bool", size: 1}
|
||||||
|
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}
|
||||||
|
String = &Array{Of: Byte}
|
||||||
|
UInt64 = &Base{name: "uint64", size: 8}
|
||||||
|
UInt32 = &Base{name: "uint32", size: 4}
|
||||||
|
UInt16 = &Base{name: "uint16", size: 2}
|
||||||
|
UInt8 = &Base{name: "uint8", size: 1}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Byte = UInt8
|
||||||
|
Float = Float64
|
||||||
|
Int = Int64
|
||||||
|
UInt = UInt64
|
||||||
|
)
|
47
src/types/Is.go
Normal file
47
src/types/Is.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
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 == b || b == Any || a == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
aPointer, aIsPointer := a.(*Pointer)
|
||||||
|
bPointer, bIsPointer := b.(*Pointer)
|
||||||
|
|
||||||
|
if aIsPointer && bIsPointer && (bPointer.To == Any || aPointer.To == bPointer.To) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
aArray, aIsArray := a.(*Array)
|
||||||
|
|
||||||
|
if aIsArray && bIsPointer && (bPointer.To == Any || aArray.Of == bPointer.To) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
bArray, bIsArray := b.(*Array)
|
||||||
|
|
||||||
|
if aIsArray && bIsArray && (bArray.Of == Any || aArray.Of == bArray.Of) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if a == AnyInt {
|
||||||
|
switch b {
|
||||||
|
case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8, AnyInt:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b == AnyInt {
|
||||||
|
switch a {
|
||||||
|
case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8, AnyInt:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
16
src/types/Pointer.go
Normal file
16
src/types/Pointer.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
// Pointer is the address of an object.
|
||||||
|
type Pointer struct {
|
||||||
|
To Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the type name.
|
||||||
|
func (p *Pointer) Name() string {
|
||||||
|
return "*" + p.To.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the total size in bytes.
|
||||||
|
func (p *Pointer) Size() int {
|
||||||
|
return 8
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
type Type interface{}
|
// Type is the generic interface for different data types.
|
||||||
|
type Type interface {
|
||||||
|
Name() string
|
||||||
|
Size() int
|
||||||
|
}
|
61
src/types/types_test.go
Normal file
61
src/types/types_test.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package types_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/types"
|
||||||
|
"git.urbach.dev/go/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestName(t *testing.T) {
|
||||||
|
assert.Equal(t, types.Int.Name(), "int64")
|
||||||
|
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(), "[]uint8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSize(t *testing.T) {
|
||||||
|
assert.Equal(t, types.Int.Size(), 8)
|
||||||
|
assert.Equal(t, types.Int8.Size(), 1)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBasics(t *testing.T) {
|
||||||
|
assert.True(t, types.Is(types.Int, types.Int))
|
||||||
|
assert.True(t, types.Is(types.Int, types.Any))
|
||||||
|
assert.True(t, types.Is(types.Int, types.AnyInt))
|
||||||
|
assert.True(t, types.Is(types.AnyInt, types.AnyInt))
|
||||||
|
assert.True(t, types.Is(types.AnyInt, 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.AnyPointer, types.AnyInt))
|
||||||
|
assert.False(t, types.Is(types.AnyInt, types.AnyPointer))
|
||||||
|
assert.False(t, types.Is(&types.Pointer{To: types.Int}, &types.Pointer{To: types.Float}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecialCases(t *testing.T) {
|
||||||
|
// Case #1:
|
||||||
|
// For syscalls whose return type is `nil` we currently allow casting them to anything.
|
||||||
|
assert.True(t, types.Is(nil, types.Int))
|
||||||
|
assert.True(t, types.Is(nil, types.Float))
|
||||||
|
|
||||||
|
// Case #2:
|
||||||
|
// 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))
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue