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 @@
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")

Check warning on line 1546 in gnovm/pkg/gnolang/preprocess.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/preprocess.go#L1541-L1546

Added lines #L1541 - L1546 were not covered by tests
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 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 @@
// "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,11 +2340,50 @@
// 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
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

// like checkOrConvertType(last, x, nil)
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 @@
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 @@
return ""
}

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

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

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

func (ft FieldType) IsNamed() bool {
panic("unexpected")

Check warning on line 378 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L377-L378

Added lines #L377 - L378 were not covered by tests
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}

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

Expand Down Expand Up @@ -528,6 +537,10 @@
return ""
}

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

Check warning on line 541 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L540-L541

Added lines #L540 - L541 were not covered by tests
}

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

Expand Down Expand Up @@ -574,6 +587,10 @@
return ""
}

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

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

Expand Down Expand Up @@ -612,6 +629,10 @@
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 @@
return st.PkgPath
}

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

Check warning on line 772 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L771-L772

Added lines #L771 - L772 were not covered by tests
}

// 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 @@
panic("package types has no package path (unlike package values)")
}

func (pt *PackageType) IsNamed() bool {
panic("unexpected")

Check warning on line 896 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L895-L896

Added lines #L895 - L896 were not covered by tests
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

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

Expand Down Expand Up @@ -926,6 +955,10 @@
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 @@ -1073,6 +1106,10 @@
return ""
}

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

Check warning on line 1110 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L1109-L1110

Added lines #L1109 - L1110 were not covered by tests
}

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

Expand Down Expand Up @@ -1274,6 +1311,10 @@
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 @@ -1332,6 +1373,10 @@
return ""
}

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

Check warning on line 1377 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L1376-L1377

Added lines #L1376 - L1377 were not covered by tests
}

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

Expand Down Expand Up @@ -1360,6 +1405,10 @@
panic("typeval types have no package path")
}

func (tt *TypeType) IsNamed() bool {
panic("unexpected")

Check warning on line 1409 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L1408-L1409

Added lines #L1408 - L1409 were not covered by tests
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

// ----------------------------------------
// Declared type
// Declared types have a name, base (underlying) type,
Expand Down Expand Up @@ -1444,6 +1493,10 @@
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 @@ -1710,6 +1763,14 @@
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 @@ -1838,6 +1899,10 @@
panic("blockType has no package path")
}

func (bt blockType) IsNamed() bool {
panic("unexpected")

Check warning on line 1903 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L1902-L1903

Added lines #L1902 - L1903 were not covered by tests
thehowl marked this conversation as resolved.
Show resolved Hide resolved
}

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

Expand Down Expand Up @@ -1888,6 +1953,10 @@
panic("typleType has no package path")
}

func (tt *tupleType) IsNamed() bool {
panic("unexpected")

Check warning on line 1957 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L1956-L1957

Added lines #L1956 - L1957 were not covered by tests
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}

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

Expand Down Expand Up @@ -1915,6 +1984,10 @@
panic("should not happen")
}

func (rt RefType) IsNamed() bool {
panic("unexpected")

Check warning on line 1988 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L1987-L1988

Added lines #L1987 - L1988 were not covered by tests
piux2 marked this conversation as resolved.
Show resolved Hide resolved
}

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

Expand Down Expand Up @@ -1945,6 +2018,10 @@
return mn.Type.GetPkgPath()
}

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

Check warning on line 2022 in gnovm/pkg/gnolang/types.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/types.go#L2021-L2022

Added lines #L2021 - L2022 were not covered by tests
}

// ----------------------------------------
// 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 @@
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)))

Check warning on line 238 in gnovm/pkg/gnolang/values_string.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/values_string.go#L230-L238

Added lines #L230 - L238 were not covered by tests
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 map type %v",
reflect.TypeOf(tv.V)))

Check warning on line 251 in gnovm/pkg/gnolang/values_string.go

View check run for this annotation

Codecov / codecov/patch

gnovm/pkg/gnolang/values_string.go#L243-L251

Added lines #L243 - L251 were not covered by tests
}
case *FuncType:
switch fv := tv.V.(type) {
case nil:
Expand Down
Loading
Loading