Skip to content

Commit

Permalink
handle native interface elem; handle nil interface equality
Browse files Browse the repository at this point in the history
  • Loading branch information
jaekwon committed Feb 22, 2021
1 parent 5359692 commit da6520f
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 12 deletions.
14 changes: 12 additions & 2 deletions gonative.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ func go2GnoValue(rv reflect.Value) (tv TypedValue) {
tv.V = &nativeValue{Value: rv}
return
}
REFLECT_KIND_SWITCH:
tv.T = go2GnoType(rv.Type())
switch rk := rv.Kind(); rk {
case reflect.Bool:
Expand Down Expand Up @@ -204,7 +205,12 @@ func go2GnoValue(rv reflect.Value) (tv TypedValue) {
case reflect.Func:
tv.V = &nativeValue{rv}
case reflect.Interface:
tv.V = &nativeValue{rv}
if rv.IsNil() {
tv.V = nil // nil-interface, "undefined".
} else {
rv = rv.Elem()
goto REFLECT_KIND_SWITCH
}
case reflect.Map:
tv.V = &nativeValue{rv}
case reflect.Ptr:
Expand Down Expand Up @@ -594,7 +600,11 @@ func gno2GoType(t Type) reflect.Type {
// gno.PointerValue. If rv is nil, an addressable one will be
// constructed and returned, otherwise returns rv.
func gno2GoValue(tv *TypedValue, rv reflect.Value) reflect.Value {
if tv.IsUndefined() {
if tv.IsNilInterface() {
rt := gno2GoType(tv.T)
rv = reflect.New(rt).Elem()
return rv
} else if tv.IsUndefined() {
if debug {
if !rv.IsValid() {
panic("unexpected undefined gno value")
Expand Down
2 changes: 1 addition & 1 deletion op_assign.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (m *Machine) doOpAssign() {
// NOTE: PopValues() returns a slice in
// forward order, not the usual reverse.
rvs := m.PopValues(len(s.Lhs))
for i := len(s.Rhs) - 1; 0 <= i; i-- {
for i := len(s.Lhs) - 1; 0 <= i; i-- {
// Pop lhs value and desired type.
lv := m.PopAsPointer(s.Lhs[i])
lv.Assign2(m.Realm, rvs[i])
Expand Down
7 changes: 5 additions & 2 deletions op_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,14 @@ func assertTypes(lt, rt Type) {

// TODO: can be much faster.
func isEql(lv, rv *TypedValue) bool {
if lv.IsUndefined() {
return rv.IsUndefined()
}
switch lv.T.Kind() {
case BoolKind:
return (lv.GetBool() == rv.GetBool())
case StringKind:
return (lv.V.(StringValue) == rv.V.(StringValue))
return (lv.GetString() == rv.GetString())
case IntKind:
return (lv.GetInt() == rv.GetInt())
case Int8Kind:
Expand Down Expand Up @@ -557,7 +560,7 @@ func addAssign(lv, rv *TypedValue) {
// NOTE this block is replicated in op_assign.go
switch lv.T.Kind() {
case StringKind:
lv.V = lv.GetString() + rv.GetString()
lv.V = StringValue(lv.GetString() + rv.GetString())
case IntKind:
lv.SetInt(lv.GetInt() + rv.GetInt())
case Int8Kind:
Expand Down
16 changes: 12 additions & 4 deletions preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,13 @@ func Preprocess(imp Importer, ctx BlockNode, n Node) Node {
assertTypes(lt, rt)
}
}
if lnt, ok := lt.(*nativeType); ok {
if n.Op == EQL || n.Op == NEQ {
// If == or !=, no conversions.
} else if lnt, ok := lt.(*nativeType); ok {
// If left and right are native type,
// convert left and right to gno, then
// convert result back to native.
//
// get concrete native base type.
pt := go2GnoBaseType(lnt.Type).(PrimitiveType)
// convert n.Left to (gno) pt type,
Expand All @@ -545,7 +551,8 @@ func Preprocess(imp Importer, ctx BlockNode, n Node) Node {
Source: n,
Type: lnt,
}
// reset/create n2 to preprocess children.
// reset/create n2 to preprocess
// children.
n2 := &BinaryExpr{
Left: ln,
Op: n.Op,
Expand All @@ -554,8 +561,9 @@ func Preprocess(imp Importer, ctx BlockNode, n Node) Node {
resn := Node(Call(tx, n2))
resn = Preprocess(imp, last, resn)
return resn, TRANS_CONTINUE
// NOTE: binary operations are always computed in
// gno, never with reflect.
// NOTE: binary operations are always
// computed in gno, never with
// reflect.
} else {
// nothing to do.
}
Expand Down
7 changes: 7 additions & 0 deletions tests/imports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"bytes"
"compress/flate"
"context"
"crypto/sha1"
"encoding/binary"
"encoding/xml"
Expand Down Expand Up @@ -111,6 +112,12 @@ func testImporter(out io.Writer) gno.Importer {
pkg := gno.NewPackageNode("flate", "flate", nil)
pkg.DefineGoNativeValue("BestSpeed", flate.BestSpeed)
return pkg.NewPackage(nil)
case "context":
pkg := gno.NewPackageNode("context", "context", nil)
pkg.DefineGoNativeType(reflect.TypeOf((*context.Context)(nil)).Elem())
pkg.DefineGoNativeValue("WithValue", context.WithValue)
pkg.DefineGoNativeValue("Background", context.Background)
return pkg.NewPackage(nil)
default:
panic("unknown package path " + pkgPath)
}
Expand Down
24 changes: 21 additions & 3 deletions values.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,24 @@ func (tv *TypedValue) IsUndefined() bool {
}
}
return true
} else {
return tv.IsNilInterface()
}
}

func (tv *TypedValue) IsNilInterface() bool {
if tv.T != nil && tv.T.Kind() == InterfaceKind {
if tv.V == nil {
return true
} else {
if debug {
if tv.N != [8]byte{} {
panic(fmt.Sprintf(
"corrupted TypeValue (nil interface)"))
}
}
return false
}
}
return false
}
Expand Down Expand Up @@ -622,7 +640,7 @@ func (tv *TypedValue) GetBool() bool {
return *(*bool)(unsafe.Pointer(&tv.N))
}

func (tv *TypedValue) GetString() StringValue {
func (tv *TypedValue) GetString() string {
if debug {
if tv.T != nil && tv.T.Kind() != StringKind {
panic(fmt.Sprintf(
Expand All @@ -631,9 +649,9 @@ func (tv *TypedValue) GetString() StringValue {
}
}
if tv.V == nil {
return StringValue("")
return ""
} else {
return tv.V.(StringValue)
return string(tv.V.(StringValue))
}
}

Expand Down

0 comments on commit da6520f

Please sign in to comment.