TestAny, TestDelayExpr
This commit is contained in:
@@ -418,9 +418,6 @@ func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) []
|
|||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case *ssa.Slice: // varargs: this is a varargs slice
|
case *ssa.Slice: // varargs: this is a varargs slice
|
||||||
if args, ok := p.isVArgs(v.X); ok {
|
if args, ok := p.isVArgs(v.X); ok {
|
||||||
for i, arg := range args {
|
|
||||||
args[i] = arg.Do(true)
|
|
||||||
}
|
|
||||||
return append(ret, args...)
|
return append(ret, args...)
|
||||||
}
|
}
|
||||||
case *ssa.Const:
|
case *ssa.Const:
|
||||||
@@ -435,7 +432,7 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int)
|
|||||||
n := len(vals) - hasVArg
|
n := len(vals) - hasVArg
|
||||||
ret := make([]llssa.Expr, n)
|
ret := make([]llssa.Expr, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
ret[i] = p.compileValue(b, vals[i]).Do(false)
|
ret[i] = p.compileValue(b, vals[i]).Do()
|
||||||
}
|
}
|
||||||
if hasVArg > 0 {
|
if hasVArg > 0 {
|
||||||
ret = p.compileVArg(ret, b, vals[n])
|
ret = p.compileVArg(ret, b, vals[n])
|
||||||
|
|||||||
29
ssa/expr.go
29
ssa/expr.go
@@ -42,33 +42,25 @@ func (v Expr) TypeOf() types.Type {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Do evaluates the delay expression and returns the result.
|
// Do evaluates the delay expression and returns the result.
|
||||||
func (v Expr) Do(isVArg bool) Expr {
|
func (v Expr) Do() Expr {
|
||||||
if vt := v.Type; vt.kind == vkDelayExpr {
|
if vt := v.Type; vt.kind == vkDelayExpr {
|
||||||
delay := vt.t.(*delayExprTy)
|
return vt.t.(delayExprTy)()
|
||||||
if f := delay.f; f != nil {
|
|
||||||
delay.f = nil
|
|
||||||
delay.val = f(isVArg)
|
|
||||||
}
|
|
||||||
return delay.val
|
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelayExpr returns a delay expression.
|
// DelayExpr returns a delay expression.
|
||||||
func DelayExpr(f func(isVArg bool) Expr) Expr {
|
func DelayExpr(f func() Expr) Expr {
|
||||||
return Expr{Type: &aType{t: &delayExprTy{f: f}, kind: vkDelayExpr}}
|
return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}}
|
||||||
}
|
}
|
||||||
|
|
||||||
type delayExprTy struct {
|
type delayExprTy func() Expr
|
||||||
f func(isVArg bool) Expr
|
|
||||||
val Expr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *delayExprTy) Underlying() types.Type {
|
func (p delayExprTy) Underlying() types.Type {
|
||||||
panic("don't call")
|
panic("don't call")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *delayExprTy) String() string {
|
func (p delayExprTy) String() string {
|
||||||
return "delayExpr"
|
return "delayExpr"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,10 +453,7 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
|
|||||||
}
|
}
|
||||||
t := inter.Underlying().(*types.Interface)
|
t := inter.Underlying().(*types.Interface)
|
||||||
isAny := t.Empty()
|
isAny := t.Empty()
|
||||||
fnDo := func(isVArg bool) Expr {
|
fnDo := func() Expr {
|
||||||
if isVArg { // don't need make interface
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
switch x.kind {
|
switch x.kind {
|
||||||
case vkSigned, vkUnsigned, vkFloat:
|
case vkSigned, vkUnsigned, vkFloat:
|
||||||
@@ -476,7 +465,7 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
|
|||||||
if mayDelay && isAny {
|
if mayDelay && isAny {
|
||||||
return DelayExpr(fnDo)
|
return DelayExpr(fnDo)
|
||||||
}
|
}
|
||||||
return fnDo(false)
|
return fnDo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The TypeAssert instruction tests whether interface value X has type
|
// The TypeAssert instruction tests whether interface value X has type
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ func (p Program) Bool() Type {
|
|||||||
return p.boolTy
|
return p.boolTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Any returns any type.
|
||||||
func (p Program) Any() Type {
|
func (p Program) Any() Type {
|
||||||
if p.anyTy == nil {
|
if p.anyTy == nil {
|
||||||
p.anyTy = p.Type(tyAny)
|
p.anyTy = p.Type(tyAny)
|
||||||
|
|||||||
@@ -23,6 +23,37 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
func TestMakeInterface(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
b.MakeInterface(types.NewInterfaceType(nil, nil), Expr{}, true).Do(true)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func TestDelayExpr(t *testing.T) {
|
||||||
|
a := delayExprTy(nil)
|
||||||
|
_ = a.String()
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Log("TestDelayExpr: no error?")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
a.Underlying()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAny(t *testing.T) {
|
||||||
|
prog := NewProgram(nil)
|
||||||
|
prog.SetRuntime(func() *types.Package {
|
||||||
|
ret := types.NewPackage("runtime", "runtime")
|
||||||
|
scope := ret.Scope()
|
||||||
|
name := types.NewTypeName(0, ret, "Interface", nil)
|
||||||
|
types.NewNamed(name, types.NewStruct(nil, nil), nil)
|
||||||
|
scope.Insert(name)
|
||||||
|
return ret
|
||||||
|
})
|
||||||
|
prog.Any()
|
||||||
|
}
|
||||||
|
|
||||||
func assertPkg(t *testing.T, p Package, expected string) {
|
func assertPkg(t *testing.T, p Package, expected string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if v := p.String(); v != expected {
|
if v := p.String(); v != expected {
|
||||||
|
|||||||
Reference in New Issue
Block a user