TestAny, TestDelayExpr

This commit is contained in:
xushiwei
2024-04-27 21:32:48 +08:00
parent 08da38a609
commit d432899b42
4 changed files with 42 additions and 24 deletions

View File

@@ -418,9 +418,6 @@ func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) []
switch v := v.(type) {
case *ssa.Slice: // varargs: this is a varargs slice
if args, ok := p.isVArgs(v.X); ok {
for i, arg := range args {
args[i] = arg.Do(true)
}
return append(ret, args...)
}
case *ssa.Const:
@@ -435,7 +432,7 @@ func (p *context) compileValues(b llssa.Builder, vals []ssa.Value, hasVArg int)
n := len(vals) - hasVArg
ret := make([]llssa.Expr, n)
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 {
ret = p.compileVArg(ret, b, vals[n])

View File

@@ -42,33 +42,25 @@ func (v Expr) TypeOf() types.Type {
*/
// 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 {
delay := vt.t.(*delayExprTy)
if f := delay.f; f != nil {
delay.f = nil
delay.val = f(isVArg)
}
return delay.val
return vt.t.(delayExprTy)()
}
return v
}
// DelayExpr returns a delay expression.
func DelayExpr(f func(isVArg bool) Expr) Expr {
return Expr{Type: &aType{t: &delayExprTy{f: f}, kind: vkDelayExpr}}
func DelayExpr(f func() Expr) Expr {
return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}}
}
type delayExprTy struct {
f func(isVArg bool) Expr
val Expr
}
type delayExprTy func() Expr
func (p *delayExprTy) Underlying() types.Type {
func (p delayExprTy) Underlying() types.Type {
panic("don't call")
}
func (p *delayExprTy) String() string {
func (p delayExprTy) String() string {
return "delayExpr"
}
@@ -461,10 +453,7 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
}
t := inter.Underlying().(*types.Interface)
isAny := t.Empty()
fnDo := func(isVArg bool) Expr {
if isVArg { // don't need make interface
return x
}
fnDo := func() Expr {
pkg := b.fn.pkg
switch x.kind {
case vkSigned, vkUnsigned, vkFloat:
@@ -476,7 +465,7 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
if mayDelay && isAny {
return DelayExpr(fnDo)
}
return fnDo(false)
return fnDo()
}
// The TypeAssert instruction tests whether interface value X has type

View File

@@ -195,6 +195,7 @@ func (p Program) Bool() Type {
return p.boolTy
}
// Any returns any type.
func (p Program) Any() Type {
if p.anyTy == nil {
p.anyTy = p.Type(tyAny)

View File

@@ -23,6 +23,37 @@ import (
"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) {
t.Helper()
if v := p.String(); v != expected {