Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: named and unnamed type assignment 2 of 3 #1246

Merged
merged 12 commits into from
May 31, 2024
22 changes: 22 additions & 0 deletions examples/gno.land/r/demo/tests/realm_compositelit.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package tests

type (
Word uint
nat []Word
)

var zero = &Int{
neg: true,
abs: []Word{0},
}

// structLit
type Int struct {
neg bool
abs nat
}

func GetZeroType() nat {
a := zero.abs
return a
}
19 changes: 19 additions & 0 deletions examples/gno.land/r/demo/tests/realm_method38d.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package tests

var abs nat

func (n nat) Add() nat {
return []Word{0}
}

func GetAbs() nat {
abs = []Word{0}

return abs
}

func AbsAdd() nat {
rt := GetAbs().Add()

return rt
}
60 changes: 53 additions & 7 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -1538,8 +1538,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
lhs0 := n.Lhs[0].(*NameExpr).Name
lhs1 := n.Lhs[1].(*NameExpr).Name

dt := evalStaticTypeOf(store, last, cx.X)
mt := baseOf(dt).(*MapType)
var mt *MapType
st := evalStaticTypeOf(store, last, cx.X)
if dt, ok := st.(*DeclaredType); ok {
thehowl marked this conversation as resolved.
Show resolved Hide resolved
mt = dt.Base.(*MapType)
piux2 marked this conversation as resolved.
Show resolved Hide resolved
} else if mt, ok = st.(*MapType); !ok {
panic("should not happen")
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}
// re-definitions
last.Define(lhs0, anyValue(mt.Value))
last.Define(lhs1, anyValue(BoolType))
Expand Down Expand Up @@ -2146,12 +2151,12 @@ func getResultTypedValues(cx *CallExpr) []TypedValue {
func evalConst(store Store, last BlockNode, x Expr) *ConstExpr {
// TODO: some check or verification for ensuring x
// is constant? From the machine?
cv := NewMachine(".dontcare", store)
tv := cv.EvalStatic(last, x)
cv.Release()
m := NewMachine(".dontcare", store)
cv := m.EvalStatic(last, x)
m.Release()
cx := &ConstExpr{
Source: x,
TypedValue: tv,
TypedValue: cv,
}
cx.SetAttribute(ATTR_PREPROCESSED, true)
setConstAttrs(cx)
Expand Down Expand Up @@ -2308,11 +2313,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative
// "push" expected type into shift binary's left operand.
checkOrConvertType(store, last, &bx.Left, t, autoNative)
} else if *x != nil { // XXX if x != nil && t != nil {
// check type
xt := evalStaticTypeOf(store, last, *x)
if t != nil {
checkType(xt, t, autoNative)
}
if isUntyped(xt) {
// convert type
if isUntyped(xt) { // convert if x is untyped literal
if t == nil {
t = defaultTypeOf(xt)
}
Expand All @@ -2333,13 +2340,52 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative
// default:
}
}
// convert x to destination type t
thehowl marked this conversation as resolved.
Show resolved Hide resolved
cx := Expr(Call(constType(nil, t), *x))
cx = Preprocess(store, last, cx).(Expr)
*x = cx
} else {
// if one side is declared name type and the other side is unnamed type
if isNamedConversion(xt, t) {
thehowl marked this conversation as resolved.
Show resolved Hide resolved
// covert right (xt) to the type of the left (t)
cx := Expr(Call(constType(nil, t), *x))
deelawn marked this conversation as resolved.
Show resolved Hide resolved
cx = Preprocess(store, last, cx).(Expr)
*x = cx
}
}
}
}

// Return true if we need to convert named and unnamed types in an assignment
func isNamedConversion(xt, t Type) bool {
if t == nil {
t = xt
}

// t is left hand destination type, xt is right hand expression type
// In a few special cases, we should not consider compare named and unnamed type
// case 1: if left is interface, which is unnamed, we dont convert to the left type even right is named type.
piux2 marked this conversation as resolved.
Show resolved Hide resolved

_, c1 := t.(*InterfaceType)

// case2: TypeType is used in make() new() native uverse definition and TypeType.IsNamed() will panic on unexpected.

_, oktt := t.(*TypeType)
_, oktt2 := xt.(*TypeType)
c2 := oktt || oktt2

//
if !c1 && !c2 { // carve out above two cases
// covert right to the type of left if one side is unnamed type and the other side is not

if t.IsNamed() && !xt.IsNamed() ||
!t.IsNamed() && xt.IsNamed() {
return true
}
}
return false
}

// like checkOrConvertType(last, x, nil)
func convertIfConst(store Store, last BlockNode, x Expr) {
if cx, ok := x.(*ConstExpr); ok {
Expand Down
77 changes: 77 additions & 0 deletions gnovm/pkg/gnolang/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Type interface {
String() string // for dev/debugging
Elem() Type // for TODO... types
GetPkgPath() string
IsNamed() bool // named vs unname type. property as a method
}

type TypeID string
Expand Down Expand Up @@ -323,6 +324,10 @@ func (pt PrimitiveType) GetPkgPath() string {
return ""
}

func (pt PrimitiveType) IsNamed() bool {
return true
}

// ----------------------------------------
// Field type (partial)

Expand Down Expand Up @@ -369,6 +374,10 @@ func (ft FieldType) GetPkgPath() string {
panic("FieldType is a pseudotype with no package path")
}

func (ft FieldType) IsNamed() bool {
panic("unexpected")
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// FieldTypeList

Expand Down Expand Up @@ -528,6 +537,10 @@ func (at *ArrayType) GetPkgPath() string {
return ""
}

func (at *ArrayType) IsNamed() bool {
return false
}

// ----------------------------------------
// Slice type

Expand Down Expand Up @@ -574,6 +587,10 @@ func (st *SliceType) GetPkgPath() string {
return ""
}

func (st *SliceType) IsNamed() bool {
return false
}

// ----------------------------------------
// Pointer type

Expand Down Expand Up @@ -612,6 +629,10 @@ func (pt *PointerType) GetPkgPath() string {
return pt.Elt.GetPkgPath()
}

func (pt *PointerType) IsNamed() bool {
return false
}

func (pt *PointerType) FindEmbeddedFieldType(callerPath string, n Name, m map[Type]struct{}) (
trail []ValuePath, hasPtr bool, rcvr Type, field Type, accessError bool,
) {
Expand Down Expand Up @@ -747,6 +768,10 @@ func (st *StructType) GetPkgPath() string {
return st.PkgPath
}

func (st *StructType) IsNamed() bool {
return false
}

// NOTE only works for exposed non-embedded fields.
func (st *StructType) GetPathForName(n Name) ValuePath {
for i := 0; i < len(st.Fields); i++ {
Expand Down Expand Up @@ -867,6 +892,10 @@ func (pt *PackageType) GetPkgPath() string {
panic("package types has no package path (unlike package values)")
}

func (pt *PackageType) IsNamed() bool {
panic("unexpected")
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// Interface type

Expand Down Expand Up @@ -927,6 +956,10 @@ func (it *InterfaceType) GetPkgPath() string {
return it.PkgPath
}

func (it *InterfaceType) IsNamed() bool {
return false
}

func (it *InterfaceType) FindEmbeddedFieldType(callerPath string, n Name, m map[Type]struct{}) (
trail []ValuePath, hasPtr bool, rcvr Type, ft Type, accessError bool,
) {
Expand Down Expand Up @@ -1074,6 +1107,10 @@ func (ct *ChanType) GetPkgPath() string {
return ""
}

func (ct *ChanType) IsNamed() bool {
return false
}

// ----------------------------------------
// Function type

Expand Down Expand Up @@ -1275,6 +1312,10 @@ func (ft *FuncType) GetPkgPath() string {
panic("function types have no package path")
}

func (ft *FuncType) IsNamed() bool {
return false
}

func (ft *FuncType) HasVarg() bool {
if numParams := len(ft.Params); numParams == 0 {
return false
Expand Down Expand Up @@ -1333,6 +1374,10 @@ func (mt *MapType) GetPkgPath() string {
return ""
}

func (mt *MapType) IsNamed() bool {
return false
}

// ----------------------------------------
// Type (typeval) type

Expand Down Expand Up @@ -1361,6 +1406,10 @@ func (tt *TypeType) GetPkgPath() string {
panic("typeval types have no package path")
}

func (tt *TypeType) IsNamed() bool {
panic("unexpected")
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// Declared type
// Declared types have a name, base (underlying) type,
Expand Down Expand Up @@ -1445,6 +1494,10 @@ func (dt *DeclaredType) GetPkgPath() string {
return dt.PkgPath
}

func (dt *DeclaredType) IsNamed() bool {
return true
}

func (dt *DeclaredType) DefineMethod(fv *FuncValue) {
dt.Methods = append(dt.Methods, TypedValue{
T: fv.Type,
Expand Down Expand Up @@ -1711,6 +1764,14 @@ func (nt *NativeType) GetPkgPath() string {
return "go:" + nt.Type.PkgPath()
}

func (nt *NativeType) IsNamed() bool {
if nt.Type.Name() != "" {
return true
} else {
return false
}
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

func (nt *NativeType) GnoType(store Store) Type {
if nt.gnoType == nil {
nt.gnoType = store.Go2GnoType(nt.Type)
Expand Down Expand Up @@ -1839,6 +1900,10 @@ func (bt blockType) GetPkgPath() string {
panic("blockType has no package path")
}

func (bt blockType) IsNamed() bool {
panic("unexpected")
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// tupleType

Expand Down Expand Up @@ -1889,6 +1954,10 @@ func (tt *tupleType) GetPkgPath() string {
panic("typleType has no package path")
}

func (tt *tupleType) IsNamed() bool {
panic("unexpected")
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// RefType

Expand Down Expand Up @@ -1916,6 +1985,10 @@ func (rt RefType) GetPkgPath() string {
panic("should not happen")
}

func (rt RefType) IsNamed() bool {
panic("unexpected")
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// MaybeNativeType

Expand Down Expand Up @@ -1946,6 +2019,10 @@ func (mn MaybeNativeType) GetPkgPath() string {
return mn.Type.GetPkgPath()
}

func (mn MaybeNativeType) IsNamed() bool {
return mn.Type.IsNamed()
}

// ----------------------------------------
// Kind

Expand Down
22 changes: 20 additions & 2 deletions gnovm/pkg/gnolang/values_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,29 @@ func (tv *TypedValue) Sprint(m *Machine) string {
case *ArrayType:
return tv.V.(*ArrayValue).String()
case *SliceType:
return tv.V.(*SliceValue).String()
switch sv := tv.V.(type) {
case nil:
return tv.String()
case *SliceValue:
return sv.String()
default:
panic(fmt.Sprintf(
"unexpected slice type %v",
reflect.TypeOf(tv.V)))
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}
case *StructType:
return tv.V.(*StructValue).String()
case *MapType:
return tv.V.(*MapValue).String()
switch mv := tv.V.(type) {
case nil:
return tv.String()
case *MapValue:
return mv.String()
default:
panic(fmt.Sprintf(
"unexpected slice type %v",
piux2 marked this conversation as resolved.
Show resolved Hide resolved
reflect.TypeOf(tv.V)))
}
case *FuncType:
switch fv := tv.V.(type) {
case nil:
Expand Down
Loading