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) { 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])

View File

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

View File

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

View File

@@ -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 {